From 64dc72223bfc308f487ea8c70c6f961075cd4f24 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 1 Dec 2016 00:19:04 +0100 Subject: [PATCH 001/303] @R add support for m68k-*-amiga --- gcc/Makefile.in | 2 +- gcc/amigacollect2.c | 348 ++++++++++++++++++ gcc/c/c-decl.c | 78 ++++ gcc/c/c-parser.c | 18 +- gcc/c/c-tree.h | 4 + gcc/calls.c | 2 +- gcc/collect2.c | 31 ++ gcc/config.gcc | 10 + gcc/config/m68k/amigaos-protos.h | 58 +++ gcc/config/m68k/amigaos.c | 773 +++++++++++++++++++++++++++++++++++++++ gcc/config/m68k/amigaos.h | 490 +++++++++++++++++++++++++ gcc/config/m68k/amigaos.opt | 13 + gcc/config/m68k/host-amigaos.c | 42 +++ gcc/config/m68k/m68k.c | 30 +- gcc/config/m68k/m68k.h | 5 + gcc/config/m68k/m68k.md | 2 + gcc/config/m68k/m68kamigaos.h | 424 +++++++++++++++++++++ gcc/config/m68k/m68kemb.h | 2 + gcc/config/m68k/t-amigaos | 30 ++ gcc/config/m68k/x-amigaos | 104 ++++++ gcc/config/m68k/xm-amigaos.h | 64 ++++ gcc/expr.c | 2 +- gcc/function.c | 2 +- gcc/ipa-chkp.c | 2 + gcc/tree-chkp.c | 1 + gcc/var-tracking.c | 2 +- libstdc++-v3/configure | 4 + 27 files changed, 2533 insertions(+), 10 deletions(-) create mode 100755 gcc/amigacollect2.c create mode 100755 gcc/config/m68k/amigaos-protos.h create mode 100755 gcc/config/m68k/amigaos.c create mode 100755 gcc/config/m68k/amigaos.h create mode 100755 gcc/config/m68k/amigaos.opt create mode 100755 gcc/config/m68k/host-amigaos.c create mode 100755 gcc/config/m68k/m68kamigaos.h create mode 100755 gcc/config/m68k/t-amigaos create mode 100755 gcc/config/m68k/x-amigaos create mode 100755 gcc/config/m68k/xm-amigaos.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 513f9c57013f..c1986279752f 100644 --- gcc/Makefile.in +++ gcc/Makefile.in @@ -1985,7 +1985,7 @@ gcc-nm.c: gcc-ar.c cp $^ $@ COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o \ - collect-utils.o file-find.o hash-table.o + collect-utils.o file-find.o hash-table.o $(EXTRA_COLLECT2_OBJS) COLLECT2_LIBS = @COLLECT2_LIBS@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) # Don't try modifying collect2 (aka ld) in place--it might be linking this. diff --git a/gcc/amigacollect2.c b/gcc/amigacollect2.c new file mode 100755 index 000000000000..941ea0248fbe --- /dev/null +++ gcc/amigacollect2.c @@ -0,0 +1,348 @@ +/* GG-local whole file: dynamic libraries */ +/* Supplimentary functions that get compiled and linked to collect2 for + AmigaOS target. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" + +/* From collect2.c: */ + +void maybe_unlink(const char *); +void fatal_error(location_t, const char *, ...); +void fork_execute(const char *, char **, bool); + +extern char *c_file_name; +extern int debug; + +/* Local functions. */ + +static void safename (char *); +static void add_lib (const char *); +static void cat (const char *, FILE *); + + /* Names of temporary files we create. */ +#define XLIBS_C_NAME "xlibs.c" +#define XLIBS_O_NAME "xlibs.o" +#define SHARED_X_NAME "shared.x" + +/* Suffix which is prepended to "-l" options for dynamic libraries. */ +#define DYNAMIC_LIB_SUFFIX "_ixlibrary" + +/* Structure that holds library names. */ +struct liblist +{ + struct liblist *next; + char *name; + char *cname; +}; + +/* Not zero if "-static" was specified on GCC command line or if all the + libraries are static. */ +static int flag_static=0; + +/* Not zero if linking a base relative executable. This is recognized by + presence of "-m amiga_bss" on the linker's commandline. */ +static int flag_baserel=0; + +/* Not zero if some of the specified libraries are dynamic. */ +static int found_dynamic_libs=0; + +/* List of linker libraries. */ +struct liblist *head = NULL; + + /* Return 1 if collect2 should do something more apart from tlink. We want it + to call "postlink" and "strip" if linking with dynamic libraries. */ + +int +amigaos_do_collecting (void) +{ + return !flag_static; +} + +/* Check for presence of "-static" on the GCC command line. We should not do + collecting if this flag was specified. */ + +void +amigaos_gccopts_hook (const char *arg) +{ + if (strncmp(arg, "-static", strlen("-static"))==0) + flag_static=1; +} + +/* Replace unprintable characters with underscores. Used by "add_lib()". */ + +static void +safename (char *p) +{ + if (!ISALPHA(*p)) + *p = '_'; + p++; + while (*p) + { + if (!ISALNUM(*p)) + *p = '_'; + p++; + } +} + +/* Add a library to the list of dynamic libraries. First make sure that the + library is actually dynamic. Used by "amigaos_libname_hook()". */ + +static void +add_lib (const char *name) +{ + struct liblist *lib; + static char buf[256]; + + for (lib = head; lib; lib = lib->next) + if (!strcmp(lib->name, name)) + return; + + /* A2IXDIR_PREFIX is passed by "make". */ + sprintf(buf, A2IXDIR_PREFIX "/ldscripts/%s.x", name); + if (access(buf, R_OK)) + return; + + lib = (struct liblist*)xmalloc(sizeof(struct liblist)); + lib->name = xstrdup(name); + lib->cname = xstrdup(name); + safename(lib->cname); + lib->next = head; + head = lib; + + if (debug) + fprintf(stderr, "found dynamic library, name: %s, cname: %s\n", lib->name, + lib->cname); + + found_dynamic_libs=1; +} + +/* Check if the argument is a linker library. Call "add_lib()" if yes. */ + +void +amigaos_libname_hook (const char *arg) +{ + int len = strlen(arg); + if (flag_static) + return; + + if (len > 2 && !memcmp(arg, "-l", 2)) + add_lib(arg + 2); + else if (len > 2 && !strcmp(arg + len - 2, ".a")) + { + const char *lib; + + ((char*)arg)[len - 2] = '\0'; + lib = strrchr(arg, '/'); + if (lib == NULL) + lib = strrchr(arg, ':'); + if (lib == NULL) + lib = arg - 1; + if (!strncmp(lib + 1, "lib", 3)) + add_lib(lib + 4); + ((char *)arg)[len - 2] = '.'; + } +} + +/* Delete temporary files. */ + +void +amigaos_collect2_cleanup (void) +{ + if (flag_static) + return; + maybe_unlink(XLIBS_C_NAME); + maybe_unlink(XLIBS_O_NAME); + maybe_unlink(SHARED_X_NAME); +} + +/* Copy file named by FNAME to X. */ + +static void +cat (const char *fname, FILE *x) +{ +#define BUFSIZE 16384 + FILE *in; + static char buf[BUFSIZE]; + int bytes; + + in = fopen(fname, "r"); + if (in == NULL) + fatal_error (input_location, "%s", fname); + while (!feof(in) && (bytes = fread(buf, 1, BUFSIZE, in))) + fwrite(buf, 1, bytes, x); + fclose(in); +} + +/* If no dynamic libraries were found, perform like "-static". Otherwise, + create "xlibs.c", "shared.x" and invoke "gcc" to create "xlibs.o". We also + have to adjust the linker commandline. */ + +void +amigaos_prelink_hook (const char **ld1_argv, int *strip_flag) +{ + if (flag_static) + return; + + if (!found_dynamic_libs) + { + flag_static=1; + /* If the user has not requested "-static", but has requested "-s", + collect2 removes "-s" from the "ld1_argv", and calls "strip" after + linking. However, this would not be efficient if we linked the + executable without any dynamic library. In this case, we put "-s" + back. */ + if (*strip_flag) + { + /* Add "-s" as the last argument on the command line. */ + while (*ld1_argv) + ld1_argv++; + *ld1_argv++="-s"; + *ld1_argv=0; + *strip_flag=0; + } + } + else + { + FILE *x, *out; + struct liblist *lib; + static const char* argv[]={0, "-c", XLIBS_C_NAME, 0}; + const char **ld1_end, **ld1; + + /* Prepend suffixes to dynamic lib names. In addition, check if we are + linking a base relative executable. */ + for (ld1=ld1_argv; *ld1; ld1++) + { + int len=strlen(*ld1); + if (strncmp(*ld1, "-l", strlen("-l"))==0) + { + for (lib=head; lib; lib=lib->next) + if (strcmp(*ld1+strlen("-l"), lib->name)==0) + { + char *newname=(char*) + xmalloc(strlen(*ld1)+strlen(DYNAMIC_LIB_SUFFIX)+1); + strcpy(newname, *ld1); + strcat(newname, DYNAMIC_LIB_SUFFIX); + *ld1=newname; + break; + } + } + else if (len > 2 && !strcmp(*ld1 + len - 2, ".a")) + { + const char *libname; + int substituted=0; + + ((char *)(*ld1))[len - 2] = '\0'; + libname = strrchr(*ld1, '/'); + if (libname == NULL) + libname = strrchr(*ld1, ':'); + if (libname == NULL) + libname = *ld1 - 1; + if (!strncmp(libname + 1, "lib", 3)) + for (lib=head; lib; lib=lib->next) + if (strcmp(libname+4, lib->name)==0) + { + char *newname=(char*)xmalloc(strlen(*ld1)+ + strlen(DYNAMIC_LIB_SUFFIX)+3); + strcpy(newname, *ld1); + strcat(newname, DYNAMIC_LIB_SUFFIX); + strcat(newname, ".a"); + *ld1=newname; + substituted=1; + break; + } + if (!substituted) + ((char *)(*ld1))[len - 2] = '.'; + } + else if (strcmp(ld1[0], "-m")==0 && ld1[1] + && strcmp(ld1[1], "amiga_bss")==0) + { + flag_baserel=1; + break; + } + } + + out = fopen(XLIBS_C_NAME, "w"); + if (out == NULL) + fatal_error (input_location, "%s", XLIBS_C_NAME); + x = fopen(SHARED_X_NAME, "w"); + if (x == NULL) + fatal_error (input_location, "%s", SHARED_X_NAME); + + cat((flag_baserel ? A2IXDIR_PREFIX "/amiga_exe_baserel_script.x" + : A2IXDIR_PREFIX "/amiga_exe_script.x"), x); + for (lib = head; lib; lib = lib->next) + { + static char buf[256]; + sprintf(buf, A2IXDIR_PREFIX "/ldscripts/%s.x", lib->name); + fprintf(out, "extern long %sBase; long *__p%sBase = &%sBase;\n", + lib->cname, lib->cname, lib->cname); + cat(buf, x); + } /* {{ */ + fprintf(x, "}}\n"); + fclose(out); + fclose(x); + argv[0]=c_file_name; + fork_execute("gcc", (char **)argv, false); + + /* Unfortunately, unlike "-s", "-T" cannot be specified as the last + argument. We put it after "-L" args. */ + ld1_end=ld1_argv; + while (*ld1_end) + ld1_end++; + ld1_end++; + /* "ld1_end" now points after the terminating 0 of "ld1_argv". */ + + ld1=ld1_end-2; + while (ld1>ld1_argv && strncmp(*ld1, "-L", strlen("-L"))) + ld1--; + if (ld1==ld1_argv) + fatal_error (input_location, "no -L arguments"); + ld1++; + /* "ld1" now points after "-L". */ + + /* Shift all the arguments after "-L" one position right. */ + memmove(ld1+1, ld1, (ld1_end-ld1)*sizeof(*ld1)); + /* Put -Tshared.x in the now empty space. */ + *ld1="-T" SHARED_X_NAME; + } +} + +/* Be lazy and just call "postlink". */ + +void +amigaos_postlink_hook (const char *output_file) +{ + static const char *argv[]={"postlink", 0, 0, 0}; + if (flag_static) + return; + + if (flag_baserel) + { + argv[1]="-baserel"; + argv[2]=output_file; + } + else + argv[1]=output_file; + fork_execute("postlink", (char **)argv, false); +} diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index b237e93b927d..3107bdfac430 100644 --- gcc/c/c-decl.c +++ gcc/c/c-decl.c @@ -51,6 +51,8 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-ada-spec.h" #include "cilk.h" #include "builtins.h" +#include "output.h" +#include "tm_p.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -5024,6 +5026,29 @@ grokparm (const struct c_parm *parm, tree *expr) return decl; } +#ifdef TARGET_AMIGA + +/* Create a new variant of TYPE, equivalent but distinct. + This is so the caller can modify it. */ + +static tree +build_type_copy (tree type) + { + tree t, m = TYPE_MAIN_VARIANT (type); + + t = copy_node (type); + + TYPE_POINTER_TO (t) = 0; + TYPE_REFERENCE_TO (t) = 0; + + /* Add this type to the chain of variants of TYPE. */ + TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); + TYPE_NEXT_VARIANT (m) = t; + + return t; + } +#endif + /* Given a parsed parameter declaration, decode it into a PARM_DECL and push that on the current scope. EXPR is a pointer to an expression that needs to be evaluated for the side effects of array @@ -5041,6 +5066,59 @@ push_parm_decl (const struct c_parm *parm, tree *expr) decl = pushdecl (decl); +#ifdef TARGET_AMIGAOS + if (parm->asmspec) + { + tree atype = TREE_TYPE(decl); + const char *asmspec = TREE_STRING_POINTER(parm->asmspec); + if (*asmspec == '%') + ++asmspec; + int reg_number = decode_reg_name (asmspec); + + /* First detect errors in declaring global registers. */ + if (reg_number == -1) + error ("%Jregister name not specified for %qD", decl, decl); + else if (reg_number < 0) + error ("%Jinvalid register name for %qD", decl, decl); + else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode) + error ("%Jdata type of %qD isn%'t suitable for a register", decl, decl); + else if (!HARD_REGNO_MODE_OK(reg_number, TYPE_MODE (TREE_TYPE (decl)))) + error ("%Jregister specified for %qD isn%'t suitable for data type", + decl, decl); + /* Now handle properly declared static register variables. */ + else + { + /* Build tree for __attribute__ ((asm(regnum))). */ + FIXED_VALUE_TYPE fv = + { reg_number, 0, BImode }; + tree ttasm = get_identifier("asm"); + tree t, attrs = tree_cons(ttasm, build_fixed (ttasm, fv), NULL_TREE); + /* First check whether such a type already exists - if yes, use + that one. This is very important, since otherwise + common_type() would think that it sees two different + types and would try to merge them - this could result in + warning messages. */ + for (t = TYPE_MAIN_VARIANT(atype); t; t = TYPE_NEXT_VARIANT(t)) + if (comptypes (t, atype) == 1 + && attribute_list_equal (TYPE_ATTRIBUTES(t), attrs)) + break; + if (t) + atype = t; + else + { + /* Create a new variant, with differing attributes. + (Hack! Type with differing attributes should no longer be + a variant of its main type. See comment above for + explanation why this was necessary). */ + atype = build_type_copy (atype); + TYPE_ATTRIBUTES(atype) = chainon (attrs, TYPE_ATTRIBUTES(atype)); + } + TREE_TYPE(decl) = atype; +// printf("%s using %s, cdecl=%p, type=%p\n", IDENTIFIER_POINTER(DECL_NAME (decl), asmspec, decl, atype); + } + } +#endif + finish_decl (decl, input_location, NULL_TREE, NULL_TREE, NULL_TREE); } diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index c9eb8ddbae3a..d8725b572b55 100644 --- gcc/c/c-parser.c +++ gcc/c/c-parser.c @@ -3837,10 +3837,26 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs) c_parser_skip_until_found (parser, CPP_COMMA, NULL); return NULL; } + /** + * SBF: Add support for __asm("xy") register spec. + */ +#ifdef TARGET_AMIGAOS + tree asmspec = NULL_TREE; + if (c_parser_next_token_is_keyword (parser, RID_ASM)) + { + asmspec = c_parser_simple_asm_expr (parser); +// printf("asmspec: %s\n", TREE_STRING_POINTER(asmspec)); + } +#endif if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) postfix_attrs = c_parser_attributes (parser); - return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs), + + struct c_parm * cparm = build_c_parm (specs, chainon (postfix_attrs, prefix_attrs), declarator); +#ifdef TARGET_AMIGAOS + cparm->asmspec = asmspec; +#endif + return cparm; } /* Parse a string literal in an asm expression. It should not be diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index bb12a200f709..e3404fd8b0a6 100644 --- gcc/c/c-tree.h +++ gcc/c/c-tree.h @@ -453,6 +453,10 @@ struct c_parm { tree attrs; /* The declarator. */ struct c_declarator *declarator; +#ifdef TARGET_AMIGAOS + /* The optional asm spec to specify the register. */ + tree asmspec; +#endif }; /* Used when parsing an enum. Initialized by start_enum. */ diff --git a/gcc/calls.c b/gcc/calls.c index 6cc1fc721e45..e5188b93ba94 100644 --- gcc/calls.c +++ gcc/calls.c @@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" +#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "gimple.h" #include "predict.h" -#include "tm_p.h" #include "stringpool.h" #include "expmed.h" #include "optabs.h" diff --git a/gcc/collect2.c b/gcc/collect2.c index bffac802b8fe..f52a66ef1b58 100644 --- gcc/collect2.c +++ gcc/collect2.c @@ -1392,6 +1392,11 @@ main (int argc, char **argv) add_to_list (&libs, s); } #endif + /* begin-GG-local: dynamic libraries */ + #ifdef COLLECT2_LIBNAME_HOOK + COLLECT2_LIBNAME_HOOK(arg); + #endif + /* end-GG-local */ break; #ifdef COLLECT_EXPORT_LIST @@ -1492,6 +1497,11 @@ main (int argc, char **argv) add_to_list (&libs, arg); } #endif + /* begin-GG-local: dynamic libraries */ +#ifdef COLLECT2_LIBNAME_HOOK + COLLECT2_LIBNAME_HOOK(arg); +#endif + /* end-GG-local */ } } @@ -1608,6 +1618,11 @@ main (int argc, char **argv) fprintf (stderr, "\n"); } + /* begin-GG-local: dynamic libraries */ +#ifdef COLLECT2_PRELINK_HOOK + COLLECT2_PRELINK_HOOK(ld1_argv, &strip_flag); +#endif + /* end-GG-local */ /* Load the program, searching all libraries and attempting to provide undefined symbols from repository information. @@ -1648,6 +1663,8 @@ main (int argc, char **argv) } } + /* begin-GG-local: dynamic libraries */ +#ifndef COLLECT2_POSTLINK_HOOK /* Unless we have done it all already, examine the namelist and search for static constructors and destructors to call. Write the constructor and destructor tables to a .s file and reload. */ @@ -1674,6 +1691,10 @@ main (int argc, char **argv) frame_tables.number), frame_tables.number); } +#else /* COLLECT2_POSTLINK_HOOK */ + COLLECT2_POSTLINK_HOOK(output_file); +#endif +/* end-GG-local */ /* If the scan exposed nothing of special interest, there's no need to generate the glue code and relink so return now. */ @@ -1716,6 +1737,11 @@ main (int argc, char **argv) maybe_unlink (c_file); maybe_unlink (o_file); + /* begin-GG-local: dynamic libraries */ +#ifdef COLLECT2_EXTRA_CLEANUP + COLLECT2_EXTRA_CLEANUP(); +#endif + /* end-GG-local */ return 0; } @@ -1821,6 +1847,11 @@ main (int argc, char **argv) maybe_unlink (export_file); #endif + /* begin-GG-local: dynamic libraries */ +#ifdef COLLECT2_EXTRA_CLEANUP + COLLECT2_EXTRA_CLEANUP(); +#endif + /* end-GG-local */ return 0; } diff --git a/gcc/config.gcc b/gcc/config.gcc index 1d5b23f228d2..3ef1a5f110f3 100644 --- gcc/config.gcc +++ gcc/config.gcc @@ -1931,6 +1931,16 @@ m68k-*-elf* | fido-*-elf*) ;; esac ;; +m68k*-*-amigaos*) + default_m68k_cpu=68000 + tm_file="${tm_file} dbx.h newlib-stdint.h m68k/m68kamigaos.h" + tm_defines="${tm_defines} MOTOROLA=1 TARGET_AMIGAOS TARGET_CPU_DEFAULT=0" + tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-amigaos" + tm_p_file="${tm_p_file} m68k/amigaos-protos.h" + extra_objs=amigaos.o + extra_options="${extra_options} m68k/amigaos.opt" + gnu_ld=yes + ;; m68k*-*-netbsdelf*) default_m68k_cpu=68020 default_cf_cpu=5475 diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h new file mode 100755 index 000000000000..66b553ab568f --- /dev/null +++ gcc/config/m68k/amigaos-protos.h @@ -0,0 +1,58 @@ +/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 + Free Software Foundation, Inc. + Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). + Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#undef TARGET_AMIGAOS +#define TARGET_AMIGAOS 1 + +extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree); + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +#undef INIT_CUMULATIVE_ARGS +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ + (amigaos_init_cumulative_args(&(CUM), (FNTYPE))) + + +extern int amigaos_restore_a4 (void); +#ifdef RTX_CODE +extern int read_only_operand (rtx); +extern void amigaos_select_section (tree, int, unsigned HOST_WIDE_INT); +extern void amigaos_encode_section_info (tree, rtx, int); +extern void amigaos_alternate_pic_setup (FILE *); +extern void amigaos_prologue_begin_hook (FILE *, int); +extern void amigaos_alternate_frame_setup_f (FILE *, int); +extern void amigaos_alternate_frame_setup (FILE *, int); +extern struct rtx_def* gen_stack_cleanup_call (rtx, rtx); +extern void amigaos_alternate_allocate_stack (rtx *); +#ifdef TREE_CODE +//extern void amigaos_function_arg_advance (CUMULATIVE_ARGS *); +extern struct rtx_def *amigaos_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree); +#endif +#endif +#ifdef TREE_CODE +extern tree amigaos_handle_decl_attribute (tree *, tree, tree, int, bool *); +extern tree amigaos_handle_type_attribute (tree *, tree, tree, int, bool *); +#endif + diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c new file mode 100755 index 000000000000..90bc3218bab7 --- /dev/null +++ gcc/config/m68k/amigaos.c @@ -0,0 +1,773 @@ +/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 + Free Software Foundation, Inc. + Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). + Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +//work without flag_writable_strings which is not in GCC4 +#define REGPARMS_68K 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "output.h" +#include "tree.h" +#include "attribs.h" +#include "flags.h" +#include "expr.h" +#include "toplev.h" +#include "tm_p.h" +#include "target.h" +#include "diagnostic-core.h" +#include "config/m68k/amigaos.h" + + +#if 0 +static int amigaos_put_in_text (tree); +static rtx gen_stack_management_call (rtx, rtx, const char *); + +/* Baserel support. */ + +/* Does operand (which is a symbolic_operand) live in text space? If + so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. + + This function is used in base relative code generation. */ + +int +read_only_operand (rtx operand) +{ + if (GET_CODE (operand) == CONST) + operand = XEXP (XEXP (operand, 0), 0); + if (GET_CODE (operand) == SYMBOL_REF) + return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + return 1; +} + +/* Choose the section to use for DECL. RELOC is true if its value contains + any relocatable expression. */ + +void +amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) +{ + // if (TREE_CODE (decl) == STRING_CST) +// { +//// flag_writable_strings /data_section not in gcc4, +////make life easy and put to same section +//// if (! flag_writable_strings) +//// readonly_data_section (); +//// else +// //data_section (); +// } +// else if (TREE_CODE (decl) == VAR_DECL) +// { +// if (TREE_READONLY (decl) +// && ! TREE_THIS_VOLATILE (decl) +// && DECL_INITIAL (decl) +// && (DECL_INITIAL (decl) == error_mark_node +// || TREE_CONSTANT (DECL_INITIAL (decl))) +// && (!flag_pic || (flag_pic<3 && !reloc) +// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))) +// readonly_data_section (); +// else +// data_section (); +// } +// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl) +// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))) +// readonly_data_section (); +// else + //data_section (); +} + +/* This function is used while generating a base relative code. + It returns 1 if a decl is not relocatable, i. e., if it can be put + in the text section. + Currently, it's very primitive: it just checks if the object size + is less than 4 bytes (i. e., if it can hold a pointer). It also + supports arrays and floating point types. */ + +static int +amigaos_put_in_text (tree decl) +{ + tree type = TREE_TYPE (decl); + if (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0 + && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32) + || FLOAT_TYPE_P (type); +} + +/* Record properties of a DECL into the associated SYMBOL_REF. */ + +void +amigaos_encode_section_info (tree decl, rtx rtl, int first) +{ + default_encode_section_info (decl, rtl, first); + + + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + else + { + if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl) + && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST + ) + || amigaos_put_in_text (decl))) + || (TREE_CODE (decl) == VAR_DECL + && DECL_SECTION_NAME (decl) != NULL)) + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + } +} + +/* Common routine used to check if a4 should be preserved/restored. */ + +int +amigaos_restore_a4 (void) +{ + return (flag_pic >= 3 && + (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4 + || lookup_attribute ("saveds", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))); +} + +void +amigaos_alternate_pic_setup (FILE *stream) +{ + if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) + asm_fprintf (stream, "\tjbsr %U__restore_a4\n"); + else if (lookup_attribute ("saveds", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n"); +} + +/* Attributes support. */ + +#define AMIGA_CHIP_SECTION_NAME ".datachip" + +/* Handle a "chip" attribute; + arguments as in struct attribute_spec.handler. */ + +tree +amigaos_handle_decl_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == VAR_DECL) + { + if (is_attribute_p ("chip", name)) +#ifdef TARGET_ASM_NAMED_SECTION + { + if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node)) + error ("`chip' attribute cannot be specified for local variables"); + else + { + /* The decl may have already been given a section attribute from + a previous declaration. Ensure they match. */ + if (DECL_SECTION_NAME (*node) == NULL_TREE) + DECL_SECTION_NAME (*node) = + build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1, + AMIGA_CHIP_SECTION_NAME); + else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)), + AMIGA_CHIP_SECTION_NAME) != 0) + { + error_with_decl (*node, + "`chip' for `%s' conflicts with previous declaration"); + } + } + } +#else + error ("`chip' attribute is not supported for this target"); +#endif + } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to variables", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +//----- from 68k.c start + + + + + + +/* Stack checking and automatic extension support. */ + +void +amigaos_prologue_begin_hook (FILE *stream, int fsize) +{ + if (TARGET_STACKCHECK) + { + if (fsize < 256) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tjra %U__stkovf\n" + "\t0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n", + fsize); + } +} + +void +amigaos_alternate_frame_setup_f (FILE *stream, int fsize) +{ + if (fsize < 128) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\tlink %Ra5,%I%d:W\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n", + fsize); +} + +void +amigaos_alternate_frame_setup (FILE *stream, int fsize) +{ + if (!fsize) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I0,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else if (fsize < 128) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\taddw %I%d,%Rsp\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n", + fsize); +} + +//static rtx +//gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func) +//{ +// rtx call_insn, call, seq, name; +// start_sequence (); +// +// /* Move arg to d0. */ +// emit_move_insn (gen_rtx_REG (SImode, 0), arg); +// +// /* Generate the function reference. */ +// name = gen_rtx_SYMBOL_REF (Pmode, func); +// SYMBOL_REF_FLAG (name) = 1; +// /* If optimizing, put it in a psedo so that several loads can be merged +// into one. */ +// if (optimize && ! flag_no_function_cse) +// name = copy_to_reg (name); +// +// /* Generate the function call. */ +// call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (FUNCTION_MODE, name), +// const0_rtx); +// /* If we are doing stack extension, notify about the sp change. */ +// if (stack_pointer) +// call = gen_rtx_SET (VOIDmode, stack_pointer, call); +// +// /* Generate the call instruction. */ +// call_insn = emit_call_insn (call); +// /* Stack extension does not change memory in an unpredictable way. */ +// RTL_CONST_OR_PURE_CALL_P (call_insn) = 1; +// /* We pass an argument in d0. */ +// CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (VOIDmode, +// gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 0)), 0); +// +// seq = get_insns (); +// end_sequence (); +// return seq; +//} +// +//rtx +//gen_stack_cleanup_call (rtx stack_pointer, rtx sa) +//{ +// return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp"); +//} +// +//void +//amigaos_alternate_allocate_stack (rtx *operands) +//{ +// if (TARGET_STACKEXTEND) +// emit_insn (gen_stack_management_call (stack_pointer_rtx, operands[1], +// "__sub_d0_sp")); +// else +// { +// if (TARGET_STACKCHECK) +// emit_insn (gen_stack_management_call (0, operands[1], "__stkchk_d0")); +// anti_adjust_stack (operands[1]); +// } +// emit_move_insn (operands[0], virtual_stack_dynamic_rtx); +//} +#endif + +/* + * begin-GG-local: explicit register specification for parameters. + * + * Reworked and ported to gcc-6.2.0 by Stefan "Bebbo" Franke. + */ + +/** + * Define this here and add it to tm_p -> all know the custom type and allocate/use the correct size. + */ +struct amigaos_args +{ + int num_of_regs; + long regs_already_used; + int last_arg_reg; + int last_arg_len; + tree formal_type; /* New field: formal type of the current argument. */ +}; + +static struct amigaos_args mycum; +static CUMULATIVE_ARGS * lastcum; + +/* Argument-passing support functions. */ + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +void +amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype) +{ + struct amigaos_args * cum = &mycum; + lastcum = cump; + cum->num_of_regs = amigaos_regparm; +// printf("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs); fflush(stdout); + + /* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + + cum->last_arg_reg = -1; + cum->regs_already_used = 0; + + if (fntype) + { + if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(fntype))) + cum->num_of_regs = 0; + else + { + tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES(fntype)); + cum->num_of_regs = amigaos_regparm ? + amigaos_regparm : AMIGAOS_DEFAULT_REGPARM; + if (ratree) + { + tree args = TREE_VALUE(ratree); + + if (args && TREE_CODE (args) == TREE_LIST) + { + tree val = TREE_VALUE(args); + if (TREE_CODE (val) == INTEGER_CST) + { + int no = TREE_INT_CST_LOW(val); + if (no > 0 && no < AMIGAOS_MAX_REGPARM) + cum->num_of_regs = no; + } + } + } + } + } + else + /* Libcall. */ + cum->num_of_regs = 0; + + if (cum->num_of_regs) + { + /* If this is a vararg call, put all arguments on stack. */ + tree param, next_param; + for (param = TYPE_ARG_TYPES(fntype); param; param = next_param) + { + next_param = TREE_CHAIN(param); + if (!next_param && TREE_VALUE (param) != void_type_node) + cum->num_of_regs = 0; + } + } + + //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM) + // /* If return value is a structure, and we pass the buffer address in a + // register, we can't use this register for our own purposes. + // FIXME: Something similar would be useful for static chain. */ + // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) + // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM); + //#endif + + if (fntype) + cum->formal_type = TYPE_ARG_TYPES(fntype); + else + /* Call to compiler-support function. */ + cum->formal_type = 0; +} + +/* Update the data in CUM to advance over an argument. */ + +void +amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, + bool) +{ + struct amigaos_args * cum = &mycum; + CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v); + /* Update the data in CUM to advance over an argument. */ + + // printf("amigaos_function_arg_advance1 %p\r\n", cump); fflush(stdout); + if (cump != lastcum) + return; + + if (cum->last_arg_reg != -1) + { + int count; + for (count = 0; count < cum->last_arg_len; count++) + cum->regs_already_used |= (1 << (cum->last_arg_reg + count)); + cum->last_arg_reg = -1; + } + + if (cum->formal_type) + cum->formal_type = TREE_CHAIN(cum->formal_type); +} + +/* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. */ + +static struct rtx_def * +_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree); + +static struct rtx_def * +_m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) +{ + struct amigaos_args * cum = &mycum; + // printf("m68k_function_arg numOfRegs=%p\r\n", cum); + + if (cump != lastcum) + return 0; + + if (cum->num_of_regs) + { + int regbegin = -1, altregbegin = -1, len; + + /* FIXME: The last condition below is a workaround for a bug. */ + if (TARGET_68881 && FLOAT_MODE_P(mode) && + GET_MODE_UNIT_SIZE (mode) <= 12 + && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode)) + { + regbegin = 16; /* FPx */ + len = GET_MODE_NUNITS(mode); + } + /* FIXME: Two last conditions below are workarounds for bugs. */ + else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode) + { + if (POINTER_TYPE_P(type)) + regbegin = 8; /* Ax */ + else + regbegin = 0; /* Dx */ + altregbegin = 8 - regbegin; + len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; + } + + if (regbegin != -1) + { + int reg; + long mask; + + look_for_reg: mask = 1 << regbegin; + for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1) + if (!(cum->regs_already_used & mask)) + { + int end; + for (end = reg; end < cum->num_of_regs && end < reg + len; + end++, mask <<= 1) + if (cum->regs_already_used & mask) + break; + if (end == reg + len) + { + cum->last_arg_reg = reg + regbegin; + cum->last_arg_len = len; + break; + } + } + + if (reg == cum->num_of_regs && altregbegin != -1) + { + regbegin = altregbegin; + altregbegin = -1; + goto look_for_reg; + } + } + + if (cum->last_arg_reg != -1) + { + // printf("-> gen_rtx_REG %d\r\n", cum->last_arg_reg); + return gen_rtx_REG (mode, cum->last_arg_reg); + } + } + return 0; +} + +/* A C expression that controls whether a function argument is passed + in a register, and which register. */ + +struct rtx_def * +amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, + const_tree type, bool) +{ + struct amigaos_args * cum = &mycum; + + // printf("amigaos_function_arg %p\r\n", cum_v.p); fflush(stdout); + + CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v); + + if (cump != lastcum) + return 0; + + tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE; + if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) + { + int i; + cum->last_arg_reg = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low; + cum->last_arg_len = HARD_REGNO_NREGS(cum->last_arg_reg, mode); + + for (i = 0; i < cum->last_arg_len; i++) + if (cum->regs_already_used & (1 << (cum->last_arg_reg + i))) + { + error ("two parameters allocated for one register"); + break; + } + return gen_rtx_REG (mode, cum->last_arg_reg); + } + return _m68k_function_arg (cump, mode, type); +} + +/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, + one if they are compatible, and two if they are nearly compatible + (which causes a warning to be generated). */ + +int +amigaos_comp_type_attributes (const_tree type1, const_tree type2) +{ + printf("amigaos_comp_type_attributes\n"); + /* Functions or methods are incompatible if they specify mutually exclusive + ways of passing arguments. */ + if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE) + { + tree arg1, arg2; + arg1 = TYPE_ARG_TYPES(type1); + arg2 = TYPE_ARG_TYPES(type2); + for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2)) + { + tree attr1 = TYPE_ATTRIBUTES(arg1); + tree attr2 = TYPE_ATTRIBUTES(arg2); + if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1)))) + attr1 = NULL_TREE; + if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2)))) + attr2 = NULL_TREE; + if (attr1 && attr2) + { + if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low + != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low) + return 0; + } + else if (attr1 || attr2) + return 0; /* asm attribute only on one side. */ + } + if (arg1 || arg2) + return 0; /* different count of parameters. */ + } + return 1; +} + +/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, + one if they are compatible, and two if they are nearly compatible + (which causes a warning to be generated). */ +#if 0 +static int +m68k_comp_type_attributes (tree type1, tree type2) +{ + + /* Functions or methods are incompatible if they specify mutually + exclusive ways of passing arguments. */ + if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) + { + tree arg1, arg2; + if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != + !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) + || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != + !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) + return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */ + + arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); + arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); + if (arg1 && arg2) + { + int num1 = 0, num2 = 0; + if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) + { + tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); + if (numofregs) + num1 = TREE_INT_CST_LOW (numofregs); + } + if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) + { + tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); + if (numofregs) + num2 = TREE_INT_CST_LOW (numofregs); + } + if (num1 != num2) + return 0; /* Different numbers, or no number in one type. */ + } + } +#ifdef TARGET_AMIGAOS + return amigaos_comp_type_attributes(type1, type2); +#else + return 1; +#endif +} +#endif + +/* end-GG-local */ + + +/* Handle a "regparm", "stkparm" attribute; + arguments as in struct attribute_spec.handler. */ +tree +amigaos_handle_type_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree nnn = *node; + do { // while (0); +// printf("%p with treecode %d\n", node, TREE_CODE(nnn)); fflush(stdout); + if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE + || TREE_CODE (nnn) == METHOD_TYPE) + { + /* 'regparm' accepts one optional argument - number of registers in + single class that should be used to pass arguments. */ + if (is_attribute_p ("regparm", name)) + { +// printf ("regparm found\n"); fflush(stdout); + + if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn))) + { + error ("`regparm' and `stkparm' are mutually exclusive"); + break; + } + if (args && TREE_CODE (args) == TREE_LIST) + { + tree val = TREE_VALUE(args); +// printf ("regparm with val: %d\n", TREE_CODE(val)); + if (TREE_CODE (val) == INTEGER_CST) + { + int no = TREE_INT_CST_LOW(val); + if (no < 0 || no > AMIGAOS_MAX_REGPARM) + { + error ("`regparm' attribute: value %d not in [0 - %d]", + no, + AMIGAOS_MAX_REGPARM); + break; + } + } + else + { + error ("invalid argument(s) to `regparm' attribute"); + break; + } + } + } + else if (is_attribute_p ("stkparm", name)) + { + if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn))) + { + error ("`regparm' and `stkparm' are mutually exclusive"); + break; + } + } + else if (is_attribute_p ("stackext", name)) + { + if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn))) + { + error ("`stackext' and `interrupt' are mutually exclusive"); + break; + } + } + else if (is_attribute_p ("saveds", name)) + { + } + } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to functions", + IDENTIFIER_POINTER(name)); + } + return NULL_TREE; + } while (0); + // error case + *no_add_attrs = true; + return NULL_TREE; +} + + +extern bool +m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); + +bool +amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, + int *total, bool speed) +{ +// printf("outer: %d, opno: %d", outer_code, opno); fflush(stdout); +// debug_rtx(x); + bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); + *total *= 4; + return r; +} + + diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h new file mode 100755 index 000000000000..1a33225ab60f --- /dev/null +++ gcc/config/m68k/amigaos.h @@ -0,0 +1,490 @@ +/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 + Free Software Foundation, Inc. + Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). + Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). + + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef TARGET_AMIGAOS +#define TARGET_AMIGAOS 1 +#endif + +#if 0 +/* The function name __transfer_from_trampoline is not actually used. + The function definition just permits use of asm with operands" + (though the operand list is empty). */ + +#undef TRANSFER_FROM_TRAMPOLINE + +/* Call __flush_cache() after building the trampoline: it will call + an appropriate OS cache-clearing routine. */ + +#undef FINALIZE_TRAMPOLINE +#define FINALIZE_TRAMPOLINE(TRAMP) \ + emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__flush_cache"), \ + 0, VOIDmode, 2, (TRAMP), Pmode, \ + GEN_INT (TRAMPOLINE_SIZE), SImode) + +#endif + +/* Compile using the first 'm68k_regparm' data, address and float + registers for arguments passing. */ +/*#define SUBTARGET_OPTIONS { "regparm=", &m68k_regparm_string, \ + N_("Use this register count to pass arguments"), 0},*/ + + +/* Nonzero if we need to generate special stack-allocating insns. + On most systems they are not needed. + When they are needed, also define ALTERNATE_ALLOCATE_STACK (see m68k.md) + to perform the necessary actions. */ +//#undef TARGET_ALTERNATE_ALLOCATE_STACK +//#define TARGET_ALTERNATE_ALLOCATE_STACK 0 + + +/* Compile with stack extension. */ + +#define MASK_STACKEXTEND 0x40000000 /* 1 << 30 */ +#define TARGET_STACKEXTEND (((target_flags & MASK_STACKEXTEND) \ + && !lookup_attribute ("interrupt", \ + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) \ + || lookup_attribute ("stackext", \ + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + +///* Compile with stack checking. */ +// +#define MASK_STACKCHECK 0x20000000 /* 1 << 29 */ +#define TARGET_STACKCHECK ((target_flags & MASK_STACKCHECK) \ + && !(target_flags & MASK_STACKEXTEND) \ + && !lookup_attribute ("interrupt", \ + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) \ + && !lookup_attribute ("stackext", \ + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + +/* Compile with a4 restoring in public functions. */ + +#define MASK_RESTORE_A4 0x10000000 /* 1 << 28 */ +#define TARGET_RESTORE_A4 \ + ((target_flags & MASK_RESTORE_A4) && TREE_PUBLIC (current_function_decl)) + +/* Compile with a4 restoring in all functions. */ + +#define MASK_ALWAYS_RESTORE_A4 0x8000000 /* 1 << 27 */ +#define TARGET_ALWAYS_RESTORE_A4 (target_flags & MASK_ALWAYS_RESTORE_A4) + +/* Provide a dummy entry for the '-msmall-code' switch. This is used by + the assembler and '*_SPEC'. */ + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "small-code", 0, \ + "" /* Undocumented. */ }, \ + { "stackcheck", MASK_STACKCHECK, \ + N_("Generate stack-check code") }, \ + { "no-stackcheck", - MASK_STACKCHECK, \ + N_("Do not generate stack-check code") }, \ + { "stackextend", MASK_STACKEXTEND, \ + N_("Generate stack-extension code") }, \ + { "no-stackextend", - MASK_STACKEXTEND, \ + N_("Do not generate stack-extension code") }, \ + { "fixedstack", - (MASK_STACKCHECK|MASK_STACKEXTEND), \ + N_("Do not generate stack-check/stack-extension code") }, \ + { "restore-a4", MASK_RESTORE_A4, \ + N_("Restore a4 in public functions") }, \ + { "no-restore-a4", - MASK_RESTORE_A4, \ + N_("Do not restore a4 in public functions") }, \ + { "always-restore-a4", MASK_ALWAYS_RESTORE_A4, \ + N_("Restore a4 in all functions") }, \ + { "no-always-restore-a4", - MASK_ALWAYS_RESTORE_A4, \ + N_("Do not restore a4 in all functions") } + +#if 0 +/* Various ABI issues. */ + +/* This is (almost;-) BSD, so it wants DBX format. */ +#undef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +/* GDB goes mad if it sees the function end marker. */ + +#define NO_DBX_FUNCTION_END 1 + +/* Allow folding division by zero. */ + +#define REAL_INFINITY + +/* Don't try using XFmode since we don't have appropriate runtime software + support. */ +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* We use A4 for the PIC pointer, not A5, which is the framepointer. */ + +#undef PIC_OFFSET_TABLE_REGNUM +#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM) + +#undef PIC_REG +#define PIC_REG 12 + +/* Use A5 as framepointer instead of A6, since the AmigaOS ABI requires A6 + to be used as a shared library base pointer in direct library calls. */ + +#undef FRAME_POINTER_REGNUM +#define FRAME_POINTER_REGNUM 13 + +#undef M68K_REGNAME +#define M68K_REGNAME(r) ( \ + ( ((r) == FRAME_POINTER_REGNUM) \ + && frame_pointer_needed) ? \ + M68K_FP_REG_NAME : reg_names[(r)]) + + +/* The AmigaOS ABI does not define how structures should be returned, so, + contrary to 'm68k.h', we prefer a multithread-safe solution. */ + +#undef PCC_STATIC_STRUCT_RETURN + +/* Setup a default shell return value for those (gazillion..) programs that + (inspite of ANSI-C) declare main() to be void (or even VOID...) and thus + cause the shell to randomly caugh upon executing such programs (contrary + to Unix, AmigaOS scripts are terminated with an error if a program returns + with an error code above the `error' or even `failure' level + (which is configurable with the FAILAT command)). */ + +//+2004-06-24 Ulrich Weigand +//+ +//+ * c-decl.c (finish_function): Do not check for DEFAULT_MAIN_RETURN. +//+ * system.h (DEFAULT_MAIN_RETURN): Poison. +//+ * doc/tm.texi (DEFAULT_MAIN_RETURN): Remove documentation. +//+ + +//poison VAR +//#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node) + +#undef WCHAR_TYPE +#define WCHAR_TYPE "unsigned int" + +/* XXX: section support */ +#if 0 +/* Support sections in chip memory, currently '.datachip' only. */ +#undef TARGET_ASM_NAMED_SECTION +#define TARGET_ASM_NAMED_SECTION amiga_named_section + +/* We define TARGET_ASM_NAMED_SECTION, but we don't support arbitrary sections, + including '.gcc_except_table', so we emulate the standard behaviour. */ +#undef TARGET_ASM_EXCEPTION_SECTION +#define TARGET_ASM_EXCEPTION_SECTION amiga_exception_section + +#undef TARGET_ASM_EH_FRAME_SECTION +#define TARGET_ASM_EH_FRAME_SECTION amiga_eh_frame_section +#endif + +/* Use sjlj exceptions because dwarf work only on elf targets */ +#undef DWARF2_UNWIND_INFO +#define DWARF2_UNWIND_INFO 0 + + +/* This is how to output an assembler line that says to advance the + location counter to a multiple of 2**LOG bytes. */ + +#ifndef ALIGN_ASM_OP +#define ALIGN_ASM_OP "\t.align\t" +#endif + +/* GAS supports alignment up to 32768 bytes. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE, LOG) \ +do \ + { \ + if ((LOG) == 1) \ + fprintf ((FILE), "\t.even\n"); \ + else \ + fprintf ((FILE), "\t.align %d\n", (LOG)); \ + } \ +while (0) + +/* Baserel support. */ + +/* Given that symbolic_operand(X), return TRUE if no special + base relative relocation is necessary */ + +#define LEGITIMATE_BASEREL_OPERAND_P(X) \ + (flag_pic >= 3 && read_only_operand (X)) + +#undef LEGITIMATE_PIC_OPERAND_P +#define LEGITIMATE_PIC_OPERAND_P(X) \ + (! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X)) + +/* Define this macro if references to a symbol must be treated + differently depending on something about the variable or + function named by the symbol (such as what section it is in). + + The macro definition, if any, is executed immediately after the + rtl for DECL or other node is created. + The value of the rtl will be a `mem' whose address is a + `symbol_ref'. + + The usual thing for this macro to do is to a flag in the + `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified + name string in the `symbol_ref' (if one bit is not enough + information). + + On the Amiga we use this to indicate if references to a symbol should be + absolute or base relative. */ + +#undef TARGET_ENCODE_SECTION_INFO +#define TARGET_ENCODE_SECTION_INFO amigaos_encode_section_info + +#define LIBCALL_ENCODE_SECTION_INFO(FUN) \ +do \ + { \ + if (flag_pic >= 3) \ + SYMBOL_REF_FLAG (FUN) = 1; \ + } \ +while (0) + +/* Select and switch to a section for EXP. */ + +//#undef TARGET_ASM_SELECT_SECTION +//#define TARGET_ASM_SELECT_SECTION amigaos_select_section + +/* Preserve A4 for baserel code if necessary. */ + +#define EXTRA_SAVE_REG(REGNO) \ +do { \ + if (flag_pic && flag_pic >= 3 && REGNO == PIC_OFFSET_TABLE_REGNUM \ + && amigaos_restore_a4()) \ + return true; \ +} while (0) + +/* Predicate for ALTERNATE_PIC_SETUP. */ + +#define HAVE_ALTERNATE_PIC_SETUP (flag_pic >= 3) + +/* Make a4 point at data hunk. */ + +#define ALTERNATE_PIC_SETUP(STREAM) \ + (amigaos_alternate_pic_setup (STREAM)) + +/* Attribute support. */ + +/* Generate the test of d0 before return to set cc register in 'interrupt' + function. */ + +#define EPILOGUE_END_HOOK(STREAM) \ +do \ + { \ + if (lookup_attribute ("interrupt", \ + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) \ + asm_fprintf ((STREAM), "\ttstl %Rd0\n"); \ + } \ +while (0) + + +/* Stack checking and automatic extension support. */ + +#define PROLOGUE_BEGIN_HOOK(STREAM, FSIZE) \ + (amigaos_prologue_begin_hook ((STREAM), (FSIZE))) + +#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND + +#define ALTERNATE_FRAME_SETUP_F(STREAM, FSIZE) \ + (amigaos_alternate_frame_setup_f ((STREAM), (FSIZE))) + +#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND + +#define ALTERNATE_FRAME_SETUP(STREAM, FSIZE) \ + (amigaos_alternate_frame_setup ((STREAM), (FSIZE))) + +#define HAVE_ALTERNATE_FRAME_DESTR_F(FSIZE) \ + (TARGET_STACKEXTEND && current_function_calls_alloca) + +#define ALTERNATE_FRAME_DESTR_F(STREAM, FSIZE) \ + (asm_fprintf ((STREAM), "\tjra %U__unlk_a5_rts\n")) + +#define HAVE_ALTERNATE_RETURN \ + (TARGET_STACKEXTEND && frame_pointer_needed && \ + current_function_calls_alloca) + +#define ALTERNATE_RETURN(STREAM) + +#if 0 +#define HAVE_restore_stack_nonlocal TARGET_STACKEXTEND +#define gen_restore_stack_nonlocal gen_stack_cleanup_call + +#define HAVE_restore_stack_function TARGET_STACKEXTEND +#define gen_restore_stack_function gen_stack_cleanup_call + +#define HAVE_restore_stack_block TARGET_STACKEXTEND +#define gen_restore_stack_block gen_stack_cleanup_call + +#undef TARGET_ALTERNATE_ALLOCATE_STACK +#define TARGET_ALTERNATE_ALLOCATE_STACK 1 + +#define ALTERNATE_ALLOCATE_STACK(OPERANDS) \ +do \ + { \ + amigaos_alternate_allocate_stack (OPERANDS); \ + DONE; \ + } \ +while (0) +#endif + +/* begin-GG-local: dynamic libraries */ + +extern int amigaos_do_collecting (void); +extern void amigaos_gccopts_hook (const char *); +extern void amigaos_libname_hook (const char* arg); +extern void amigaos_collect2_cleanup (void); +extern void amigaos_prelink_hook (const char **, int *); +extern void amigaos_postlink_hook (const char *); + +/* This macro is used to check if all collect2 facilities should be used. + We need a few special ones, like stripping after linking. */ + +#define DO_COLLECTING (do_collecting || amigaos_do_collecting()) +#define COLLECT2_POSTLINK_HOOK(OUTPUT_FILE) amigaos_postlink_hook(OUTPUT_FILE) //new + +/* This macro is called in collect2 for every GCC argument name. + ARG is a part of commandline (without '\0' at the end). */ + +#define COLLECT2_GCC_OPTIONS_HOOK(ARG) amigaos_gccopts_hook(ARG) + +/* This macro is called in collect2 for every ld's "-l" or "*.o" or "*.a" + argument. ARG is a complete argument, with '\0' at the end. */ + +#define COLLECT2_LIBNAME_HOOK(ARG) amigaos_libname_hook(ARG) + +/* This macro is called at collect2 exit, to clean everything up. */ + +#define COLLECT2_EXTRA_CLEANUP amigaos_collect2_cleanup + +/* This macro is called just before the first linker invocation. + LD1_ARGV is "char** argv", which will be passed to "ld". STRIP is an + *address* of "strip_flag" variable. */ + +#define COLLECT2_PRELINK_HOOK(LD1_ARGV, STRIP) \ +amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP)) + +/* This macro is called just after the first linker invocation, in place of + "nm" and "ldd". OUTPUT_FILE is the executable's filename. */ + +#define COLLECT2_POSTLINK_HOOK(OUTPUT_FILE) amigaos_postlink_hook(OUTPUT_FILE) +/* end-GG-local */ + +#endif + +/* begin-GG-local: explicit register specification for parameters */ + +/* Note: this is an extension of m68k_args */ + + +/* A C type for declaring a variable that is used as the first + argument of `FUNCTION_ARG' and other related values. */ +/* Max. number of data, address and float registers to be used for passing + integer, pointer and float arguments when TARGET_REGPARM. + It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */ +#undef AMIGAOS_MAX_REGPARM +#define AMIGAOS_MAX_REGPARM 4 + +/* The default number of data, address and float registers to use when + user specified '-mregparm' switch, not '-mregparm=' option. */ +#undef AMIGAOS_DEFAULT_REGPARM +#define AMIGAOS_DEFAULT_REGPARM 2 + + +#undef CLASS_MAX_NREGS +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((CLASS) == FP_REGS ? GET_MODE_NUNITS (MODE) \ + : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + +/* 1 if N is a possible register number for function argument passing. */ +#undef FUNCTION_ARG_REGNO_P +#define FUNCTION_ARG_REGNO_P(N) \ + ((((int)N) >= 0 && (N) < AMIGAOS_MAX_REGPARM) \ + || ((N) >= 8 && (N) < 8 + AMIGAOS_MAX_REGPARM) \ + || (TARGET_68881 && (N) >= 16 && (N) < 16 + AMIGAOS_MAX_REGPARM)) + +/* + On the m68k, this is a structure: + num_of_regs: number of data, address and float registers to use for + arguments passing (if it's 2, than pass arguments in d0, d1, a0, a1, + fp0 and fp1). 0 - pass everything on stack. vararg calls are + always passed entirely on stack. + regs_already_used: bitmask of the already used registers. + last_arg_reg - register number of the most recently passed argument. + -1 if passed on stack. + last_arg_len - number of registers used by the most recently passed + argument. +*/ + +extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *cum, tree); +extern void amigaos_function_arg_advance (cumulative_args_t, machine_mode, const_tree, bool); +extern rtx amigaos_function_arg (cumulative_args_t, machine_mode, const_tree, bool); +extern cumulative_args_t amigaos_pack_cumulative_args (CUMULATIVE_ARGS *); +extern int amigaos_comp_type_attributes (const_tree, const_tree); +extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*); + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE amigaos_function_arg_advance + +/* A C expression that controls whether a function argument is passed + in a register, and which register. */ + +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG amigaos_function_arg + +#undef TARGET_PACK_CUMULATIVE_ARGS +#define TARGET_PACK_CUMULATIVE_ARGS(CUM) \ + (amigaos_pack_cumulative_args(&(CUM))) + +#undef TARGET_COMP_TYPE_ATTRIBUTES +#define TARGET_COMP_TYPE_ATTRIBUTES amigaos_comp_type_attributes + + +/* end-GG-local */ + +#undef SUBTARGET_OVERRIDE_OPTIONS +#define SUBTARGET_OVERRIDE_OPTIONS \ +do \ + { \ + if (!TARGET_68020 && flag_pic==4) \ + error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \ + if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \ + error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \ + } \ +while (0) + +/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, + affects_type_identity } */ +#define SUBTARGET_ATTRIBUTES \ + { "regparm", 1, 1, true, false, false, amigaos_handle_type_attribute,\ + false }, + +#define GOT_SYMBOL_NAME "" + +#undef TARGET_RTX_COSTS +#define TARGET_RTX_COSTS amigaos_rtx_costs +bool +amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool); + diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt new file mode 100755 index 000000000000..a9bc80c4f5b6 --- /dev/null +++ gcc/config/m68k/amigaos.opt @@ -0,0 +1,13 @@ + +mregparm= +Target RejectNegative Var(amigaos_regparm) Joined UInteger +Pass arguments through registers. + +noixemul +Target RejectNegative +Do not use ixemul.library - use libnix instead to link + +msmall-code +Target RejectNegative +small code model + diff --git a/gcc/config/m68k/host-amigaos.c b/gcc/config/m68k/host-amigaos.c new file mode 100755 index 000000000000..8c72d516a378 --- /dev/null +++ gcc/config/m68k/host-amigaos.c @@ -0,0 +1,42 @@ +/* AmigaOS/m68k host-specific hook definitions. + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "hosthooks.h" +#include "hosthooks-def.h" +#include "toplev.h" + +static void * amigaos_m68k_gt_pch_get_address (size_t); + +/* Return the address of the PCH address space, if the PCH will fit in it. */ + +static void * +amigaos_m68k_gt_pch_get_address (size_t sz ATTRIBUTE_UNUSED) +{ + fatal_error ("PCH not supported\n"); +} + +#undef HOST_HOOKS_GT_PCH_GET_ADDRESS +#define HOST_HOOKS_GT_PCH_GET_ADDRESS amigaos_m68k_gt_pch_get_address + +const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; \ No newline at end of file diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 03f474e1b63c..fe3a939e1530 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -166,7 +166,10 @@ static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); static bool m68k_ok_for_sibcall_p (tree, tree); static bool m68k_tls_symbol_p (rtx); static rtx m68k_legitimize_address (rtx, rtx, machine_mode); -static bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); +#ifndef TARGET_AMIGAOS +static +#endif +bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); #if M68K_HONOR_TARGET_STRICT_ALIGNMENT static bool m68k_return_in_memory (const_tree, const_tree); #endif @@ -174,10 +177,12 @@ static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; static void m68k_trampoline_init (rtx, tree, rtx); static int m68k_return_pops_args (tree, tree, int); static rtx m68k_delegitimize_address (rtx); +#ifndef TARGET_AMIGA static void m68k_function_arg_advance (cumulative_args_t, machine_mode, const_tree, bool); static rtx m68k_function_arg (cumulative_args_t, machine_mode, const_tree, bool); +#endif static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x); static bool m68k_output_addr_const_extra (FILE *, rtx); static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; @@ -322,6 +327,10 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128 +#ifdef TARGET_AMIGA +#include "amigaos.h" +#endif + static const struct attribute_spec m68k_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, @@ -332,6 +341,9 @@ static const struct attribute_spec m68k_attribute_table[] = m68k_handle_fndecl_attribute, false }, { "interrupt_thread", 0, 0, true, false, false, m68k_handle_fndecl_attribute, false }, +#ifdef SUBTARGET_ATTRIBUTES + SUBTARGET_ATTRIBUTES +#endif { NULL, 0, 0, false, false, false, NULL, false } }; @@ -1419,6 +1431,7 @@ m68k_ok_for_sibcall_p (tree decl, tree exp) return false; } +#ifndef TARGET_AMIGA /* On the m68k all args are always pushed. */ static rtx @@ -1440,6 +1453,7 @@ m68k_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, ? (GET_MODE_SIZE (mode) + 3) & ~3 : (int_size_in_bytes (type) + 3) & ~3); } +#endif /* Convert X to a legitimate function call memory reference and return the result. */ @@ -2172,6 +2186,8 @@ m68k_get_gp (void) if (pic_offset_table_rtx == NULL_RTX) pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_REG); +// debug_rtx(pic_offset_table_rtx); + crtl->uses_pic_offset_table = 1; return pic_offset_table_rtx; @@ -2442,9 +2458,9 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) { gcc_assert (reg); - pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg); pic_ref = m68k_move_to_reg (pic_ref, orig, reg); +// debug_rtx(pic_ref); } else if (GET_CODE (orig) == CONST) { @@ -2787,7 +2803,10 @@ const_int_cost (HOST_WIDE_INT i) } } -static bool +#ifndef TARGET_AMIGAOS +static +#endif +bool m68k_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED, int *total, bool speed ATTRIBUTE_UNUSED) @@ -4424,6 +4443,7 @@ floating_exact_log2 (rtx x) void print_operand (FILE *file, rtx op, int letter) { +// printf("letter: %c\n", letter); if (letter == '.') { if (MOTOROLA) @@ -4521,7 +4541,9 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc) switch (reloc) { case RELOC_GOT: - if (MOTOROLA) + if (TARGET_AMIGAOS) + return ""; + else if (MOTOROLA) { if (flag_pic == 1 && TARGET_68020) return "@GOT.w"; diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 2aa858fa23b5..74d5aa042059 100644 --- gcc/config/m68k/m68k.h +++ gcc/config/m68k/m68k.h @@ -971,3 +971,8 @@ extern int m68k_sched_address_bypass_p (rtx_insn *, rtx_insn *); extern int m68k_sched_indexed_address_bypass_p (rtx_insn *, rtx_insn *); #define CPU_UNITS_QUERY 1 + +#if 1 +extern void default_stabs_asm_out_constructor (rtx, int); +extern void default_stabs_asm_out_destructor (rtx, int); +#endif diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index ec37bd76f55f..f5b63f43c372 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -7092,6 +7092,8 @@ operands[1] = gen_rtx_REG (Pmode, PIC_REG); return MOTOROLA ? "move.l %?(%1),%0" : "movel %1@(%?), %0"; } + else if (TARGET_AMIGAOS) + return "lea (%%pc, __GLOBAL_OFFSET_TABLE_), %0"; else if (MOTOROLA) { if (TARGET_COLDFIRE) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h new file mode 100755 index 000000000000..0ce599138c7d --- /dev/null +++ gcc/config/m68k/m68kamigaos.h @@ -0,0 +1,424 @@ +/* m68kelf support, derived from m68kv4.h */ + +/* Target definitions for GNU compiler for mc680x0 running AmigaOs + Copyright (C) 1991-2016 Free Software Foundation, Inc. + + Written by Ron Guilmette (rfg@netcom.com) and Fred Fish (fnf@cygnus.com). + +This file is part of GCC. + +GCC 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 3, or (at your option) +any later version. + +GCC 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 GCC; see the file COPYING3. If not see +. */ + +#ifndef TARGET_AMIGA +#define TARGET_AMIGA 1 +#endif + +#ifndef SWBEG_ASM_OP +#define SWBEG_ASM_OP "\t.swbeg\t" +#endif + +#undef PIC_REG +#define PIC_REG 12 + +#undef FRAME_POINTER_REGNUM +#define FRAME_POINTER_REGNUM 13 + +#undef M68K_REGNAME +#define M68K_REGNAME(r) ( \ + ( ((r) == FRAME_POINTER_REGNUM) \ + && frame_pointer_needed) ? \ + M68K_FP_REG_NAME : reg_names[(r)]) + + + +/* Here are three prefixes that are used by asm_fprintf to + facilitate customization for alternate assembler syntaxes. + Machines with no likelihood of an alternate syntax need not + define these and need not use asm_fprintf. */ + +/* The prefix for register names. Note that REGISTER_NAMES + is supposed to include this prefix. Also note that this is NOT an + fprintf format string, it is a literal string */ + +#undef REGISTER_PREFIX +#define REGISTER_PREFIX "" + +/* The prefix for local (compiler generated) labels. + These labels will not appear in the symbol table. */ + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX "." + +/* The prefix to add to user-visible assembler symbols. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "_" + +/* config/m68k.md has an explicit reference to the program counter, + prefix this by the register prefix. */ + +#define ASM_RETURN_CASE_JUMP \ + do { \ + return "jmp %%pc@(2,%0:w)"; \ + } while (0) + +/* This is how to output an assembler line that says to advance the + location counter to a multiple of 2**LOG bytes. */ + +#ifndef ALIGN_ASM_OP +#define ALIGN_ASM_OP "\t.align\t" +#endif + +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ +do { \ + if ((LOG) > 0) \ + fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \ +} while (0) + +/* Register in which address to store a structure value is passed to a + function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */ + +#undef M68K_STRUCT_VALUE_REGNUM +#define M68K_STRUCT_VALUE_REGNUM A0_REG + +/* The static chain regnum defaults to a0, but we use that for + structure return, so have to use a1 for the static chain. */ + +#undef STATIC_CHAIN_REGNUM +#define STATIC_CHAIN_REGNUM A1_REG +#undef M68K_STATIC_CHAIN_REG_NAME +#define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a1" + +#define ASM_COMMENT_START "|" + +/* Define how the m68k registers should be numbered for Dwarf output. + The numbering provided here should be compatible with the native + SVR4 SDB debugger in the m68k/SVR4 reference port, where d0-d7 + are 0-7, a0-a8 are 8-15, and fp0-fp7 are 16-23. */ + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +#if 0 +/* SVR4 m68k assembler is bitching on the `comm i,1,1' which askes for + 1 byte alignment. Don't generate alignment for COMMON seems to be + safer until we the assembler is fixed. */ +#undef ASM_OUTPUT_ALIGNED_COMMON +/* Same problem with this one. */ +#undef ASM_OUTPUT_ALIGNED_LOCAL +#endif + +#undef ASM_OUTPUT_COMMON +#undef ASM_OUTPUT_LOCAL +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +( fputs (".comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (int)(SIZE))) + +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +( fputs (".lcomm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (int)(SIZE))) + +/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to + keep switch tables in the text section. */ + +#define JUMP_TABLES_IN_TEXT_SECTION 1 + +/* In m68k svr4, using swbeg is the standard way to do switch + table. */ +#undef ASM_OUTPUT_BEFORE_CASE_LABEL +#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); +/* end of stuff from m68kv4.h */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crtbegin.o%s" + +#ifndef BSS_SECTION_ASM_OP +#define BSS_SECTION_ASM_OP "\t.section\t.bss" +#endif + +#ifndef ASM_OUTPUT_ALIGNED_BSS +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) +#endif + + +/* Specs, switches. */ + +/* amiga/amigaos are the new "standard" defines for the Amiga. + MCH_AMIGA, AMIGA, __chip etc. are used in other compilers and are + provided for compatibility reasons. + When creating shared libraries, use different 'errno'. */ + + + +#undef TARGET_OS_CPP_BUILTINS +#define TARGET_OS_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("__chip=__attribute__((__chip__))"); \ + builtin_define ("__saveds=__attribute__((__saveds__))"); \ + builtin_define ("__interrupt=__attribute__((__interrupt__))"); \ + builtin_define ("__stackext=__attribute__((__stackext__))"); \ + builtin_define ("__regargs_x=__attribute__((regparm))"); \ + builtin_define ("__stdargs_x=__attribute__((stkparm))"); \ + builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \ + builtin_define_std ("amiga"); \ + builtin_define_std ("amigaos"); \ + builtin_define_std ("AMIGA"); \ + builtin_define_std ("MCH_AMIGA"); \ + builtin_assert ("system=amigaos"); \ + } \ + while (0) + +#if 0 +if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ + builtin_define ("errno=(*ixemul_errno)"); \ + +#endif + +/* Inform the program which CPU we compile for. */ + +//#undef TARGET_CPU_CPP_BUILTINS +/* + use --with-cpu=mc68040 etc.. instead on config. code was after #define TARGET_CPU_CPP_BUILTINS() + if (TARGET_68040_ONLY) \ + { \ + if (TARGET_68060) \ + builtin_define_std ("mc68060"); \ + else \ + builtin_define_std ("mc68040"); \ + } \ + else if (TARGET_68030 && !TARGET_68040) \ + builtin_define_std ("mc68030"); \ + else if (TARGET_68020) \ + builtin_define_std ("mc68020"); \ + builtin_define_std ("mc68000"); \ +*/ +/* +#define TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + builtin_define_std ("mc68040"); \ + if (flag_pic > 2) \ + { \ + builtin_define ("__pic__"); \ + if (flag_pic > 3) \ + builtin_define ("__PIC__"); \ + } \ + builtin_assert ("cpu=m68k"); \ + builtin_assert ("machine=m68k"); \ + } \ + while (0) +*/ +/* Define __HAVE_68881__ in preprocessor according to the -m flags. + This will control the use of inline 68881 insns in certain macros. + Note: it should be set in TARGET_CPU_CPP_BUILTINS but TARGET_68881 + isn't the same -m68881 since its also true for -m680[46]0 ... + Differentiate between libnix and ixemul. */ + +#define CPP_SPEC \ + "%{m68881:-D__HAVE_68881__} " \ + "%{!ansi:" \ + "%{m68020:-Dmc68020} " \ + "%{mc68020:-Dmc68020} " \ + "%{m68020-40:-Dmc68020} " \ + "%{m68020-60:-Dmc68020} " \ + "%{m68030:-Dmc68030} " \ + "%{m68040:-Dmc68040} " \ + "%{m68060:-Dmc68060}} " \ + "%{m68020:-D__mc68020__ -D__mc68020} " \ + "%{mc68020:-D__mc68020__ -D__mc68020} " \ + "%{m68020-40:-D__mc68020__ -D__mc68020} " \ + "%{m68020-60:-D__mc68020__ -D__mc68020} " \ + "%{m68030:-D__mc68030__ -D__mc68030} " \ + "%{m68040:-D__mc68040__ -D__mc68040} " \ + "%{m68060:-D__mc68060__ -D__mc68060} " \ + "%{noixemul:%{!ansi:%{!std=*:-Dlibnix}%{std=gnu*:-Dlibnix}} -D__libnix -D__libnix__} " \ + "%{!noixemul:%{!ansi:%{!std=*:-Dixemul}%{std=gnu*:-Dixemul}} -D__ixemul -D__ixemul__}" + +/* Translate '-resident' to '-fbaserel' (they differ in linking stage only). + Don't put function addresses in registers for PC-relative code. */ + +#define CC1_SPEC \ + "%{resident:-fbaserel} " \ + "%{resident32:-fbaserel32} " \ + "%{msmall-code:-fno-function-cse}" + +/* Various -m flags require special flags to the assembler. */ + +#undef ASM_SPEC +#define ASM_SPEC \ + "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" + +#undef ASM_CPU_SPEC +#define ASM_CPU_SPEC \ + "%{m68000|mc68000:-m68010} " \ + "%{m6802*|mc68020:-m68020} " \ + "%{m68030} " \ + "%{m68040} " \ + "%{m68060}" + +#define ASM_CPU_DEFAULT_SPEC \ + "%{!m680*:%{!mc680*:-m68040}}" + +/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD + compatible debug hunk. + Also, pass appropriate linker flavours depending on user-supplied + commandline options. */ + +#define LINK_SPEC \ + "%{noixemul:-fl libnix} " \ + "%{resident*:-amiga-datadata-reloc} " \ + "%{resident|fbaserel:-m amiga_bss -fl libb} " \ + "%{resident32|fbaserel32:-m amiga_bss -fl libb32} " \ + "%{g:-amiga-debug-hunk} " \ + "%(link_cpu)" + +#define LINK_CPU_SPEC \ + "%{m6802*|mc68020|m68030|m68040|m68060:-fl libm020} " \ + "%{m68881:-fl libm881}" + +/* Choose the right startup file, depending on whether we use base relative + code, base relative code with automatic relocation (-resident), their + 32-bit versions, libnix, profiling or plain crt0.o. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!noixemul:" \ + "%{fbaserel:%{!resident:bcrt0.o%s}}" \ + "%{resident:rcrt0.o%s}" \ + "%{fbaserel32:%{!resident32:lcrt0.o%s}}" \ + "%{resident32:scrt0.o%s}" \ + "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \ + "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}}" \ + "%{noixemul:" \ + "%{resident:libnix/nrcrt0.o%s} " \ + "%{!resident:%{fbaserel:libnix/nbcrt0.o%s}%{!fbaserel:libnix/ncrt0.o%s}}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{noixemul:-lstubs}" + +/* put return values in FPU build in FP0 Reg */ +#undef FUNCTION_VALUE_REGNO_P +#define FUNCTION_VALUE_REGNO_P(N) \ + ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG)) + + +/* Automatically search libamiga.a for AmigaOS specific functions. Note + that we first search the standard C library to resolve as much as + possible from there, since it has names that are duplicated in libamiga.a + which we *don't* want from there. Then search libamiga.a for any calls + that were not generated inline, and finally search the standard C library + again to resolve any references that libamiga.a might have generated. + This may only be a temporary solution since it might be better to simply + remove the things from libamiga.a that should be pulled in from libc.a + instead, which would eliminate the first reference to libc.a. Note that + if we don't search it automatically, it is very easy for the user to try + to put in a -lamiga himself and get it in the wrong place, so that (for + example) calls like sprintf come from -lamiga rather than -lc. */ + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{!noixemul:" \ + "%{p|pg:-lc_p}" \ + "%{!p:%{!pg:-lc -lamiga -lc}}}" \ + "%{noixemul:" \ + "-lnixmain -lnix -lamiga %{mstackcheck|mstackextend:-lstack}}" + +/* This macro defines names of additional specifications to put in the specs + that can be used in various specifications like CC1_SPEC. Its definition + is an initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + specification name, and a string constant that used by the GCC driver + program. + + Do not define this macro if it does not need to do anything. */ +#undef EXTRA_SPECS +#define EXTRA_SPECS \ + { "asm_cpu", ASM_CPU_SPEC }, \ + { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \ + { "link_cpu", LINK_CPU_SPEC } + + +/* begin-GG-local: dynamic libraries */ + +extern int amigaos_do_collecting (void); +extern void amigaos_gccopts_hook (const char *); +extern void amigaos_libname_hook (const char* arg); +extern void amigaos_collect2_cleanup (void); +extern void amigaos_prelink_hook (const char **, int *); +extern void amigaos_postlink_hook (const char *); + +/* This macro is used to check if all collect2 facilities should be used. + We need a few special ones, like stripping after linking. */ + +#define DO_COLLECTING (do_collecting || amigaos_do_collecting()) + +/* This macro is called in collect2 for every GCC argument name. + ARG is a part of commandline (without '\0' at the end). */ + +#define COLLECT2_GCC_OPTIONS_HOOK(ARG) amigaos_gccopts_hook(ARG) + +/* This macro is called in collect2 for every ld's "-l" or "*.o" or "*.a" + argument. ARG is a complete argument, with '\0' at the end. */ + +#define COLLECT2_LIBNAME_HOOK(ARG) amigaos_libname_hook(ARG) + +/* This macro is called at collect2 exit, to clean everything up. */ + +#define COLLECT2_EXTRA_CLEANUP amigaos_collect2_cleanup + +/* This macro is called just before the first linker invocation. + LD1_ARGV is "char** argv", which will be passed to "ld". STRIP is an + *address* of "strip_flag" variable. */ + +#define COLLECT2_PRELINK_HOOK(LD1_ARGV, STRIP) \ +amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP)) + +/* This macro is called just after the first linker invocation, in place of + "nm" and "ldd". OUTPUT_FILE is the executable's filename. */ + +#define COLLECT2_POSTLINK_HOOK(OUTPUT_FILE) amigaos_postlink_hook(OUTPUT_FILE) +/* end-GG-local */ + +#undef MAX_OFILE_ALIGNMENT +#define MAX_OFILE_ALIGNMENT ((1 << 15)*BITS_PER_UNIT) + +#if 0 +#undef INCLUDE_DEFAULTS +#define INCLUDE_DEFAULTS \ + { \ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \ + GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \ + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \ + { CROSS_INCLUDE_DIR "/../../os-include", "GCC", 0, 0 }, \ + { TOOL_INCLUDE_DIR "/../ndk/include", "GCC", 0, 0 }, \ + { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 }, \ + { 0, 0, 0, 0 } \ + } +#endif + +#undef FIXED_INCLUDE_DIR +#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../os-include" + diff --git a/gcc/config/m68k/m68kemb.h b/gcc/config/m68k/m68kemb.h index 0d8d88c74ea9..29b3e194f12d 100644 --- gcc/config/m68k/m68kemb.h +++ gcc/config/m68k/m68kemb.h @@ -32,12 +32,14 @@ #define NEEDS_UNTYPED_CALL 1 /* Target OS builtins. */ +#ifndef TARGET_OS_CPP_BUILTINS #define TARGET_OS_CPP_BUILTINS() \ do \ { \ builtin_define ("__embedded__"); \ } \ while (0) +#endif /* Override the default LIB_SPEC from gcc.c. We don't currently support profiling, or libg.a. */ diff --git a/gcc/config/m68k/t-amigaos b/gcc/config/m68k/t-amigaos new file mode 100755 index 000000000000..112d5daa06fb --- /dev/null +++ gcc/config/m68k/t-amigaos @@ -0,0 +1,30 @@ +# Makefile fragment for AmigaOS target. + +# Extra object file linked to the cc1* executables. +amigaos.o: $(srcdir)/config/m68k/amigaos.c $(CONFIG_H) + $(CXX) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) + +# Additional target dependent options for compiling libgcc.a. This just +# ensures that we don't compile libgcc* with anything other than a +# fixed stack. + +#TARGET_LIBGCC2_CFLAGS = -mfixedstack + +# Support for building multiple version of libgcc. + +LIBGCC_MULTI = .; \ + libb;@fbaserel \ + libm020;@m68020 \ + libb/libm020;@fbaserel@m68020 \ + libb32/libm020;@fbaserel32@m68020 + +### begin-GG-local: dynamic libraries +# Extra objects that get compiled and linked to collect2 + +EXTRA_COLLECT2_OBJS = amigacollect2.o + +# Build supplimentary AmigaOS target support file for collect2 +amigacollect2.o: amigacollect2.c + $(CXX) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + -DA2IXDIR_PREFIX=\"$(prefix)/share/a2ixlibrary\" $< $(OUTPUT_OPTION) +### end-GG-local diff --git a/gcc/config/m68k/x-amigaos b/gcc/config/m68k/x-amigaos new file mode 100755 index 000000000000..a8f60b80f9f4 --- /dev/null +++ gcc/config/m68k/x-amigaos @@ -0,0 +1,104 @@ +# Makefile fragment for AmigaOS host + +# Each compilation environment (Manx, Dice, GCC, SAS/C, etc) provides its +# own equivalent of the UNIX /usr/include tree. For gcc, the standard headers +# are in /gg/include and system specific headers are in /gg/os-include. +# Use these paths for fixincludes. + +SYSTEM_HEADER_DIR = $(prefix)/include + +# Uncomment the following macro to get a resident GCC. We don't do it +# by default, since we want to support users with mc68000. +# WARNING! If you uncomment this, you MUST add the same flags to the +# libiberty's Makefile (libiberty is now linked into GCC executables). + +#RESIDENT = -m68020 -resident32 + +# Additional host flags that are not used when compiling with GCC_FOR_TARGET, +# such as when compiling the libgcc* runtime archives. GCC uses stack +# a lot, and since AmigaOS provides processes with a small, fixed size +# stack, we have to generate code that will extend it whenever necessary. + +XCFLAGS = -mstackextend $(RESIDENT) + +# AmigaOS supports "AmigaGuide(R)" hypertext files. For GCC, these are +# build with a custom "makeinfo". + +# Arrange for guides to be build with GCC, in the build directory. + +### begin-GG-local: gcc-amigaos +#EXTRA_DOC_TARGETS = guide gcc-amigaos-doc +### end-GG-local + +# Actually build guides + +guide:: doc/cpp.guide doc/gcc.guide doc/gccint.guide \ + doc/gccinstall.guide doc/cppinternals.guide + +doc/cpp.guide: $(TEXI_CPP_FILES) +doc/gcc.guide: $(TEXI_GCC_FILES) +doc/gccint.guide: $(TEXI_GCCINT_FILES) +doc/cppinternals.guide: $(TEXI_CPPINT_FILES) + +doc/%.guide: %.texi + if [ x$(BUILD_INFO) = xinfo ]; then \ + $(MAKEINFO) --amiga $(MAKEINFOFLAGS) -I $(docdir) \ + -I $(docdir)/include -o $@ $<; \ + fi + +# Duplicate entry to handle renaming of gccinstall.guide +doc/gccinstall.guide: $(TEXI_GCCINSTALL_FILES) + if [ x$(BUILD_INFO) = xinfo ]; then \ + $(MAKEINFO) --amiga $(MAKEINFOFLAGS) -I $(docdir) \ + -I $(docdir)/include -o $@ install.texi; \ + fi + +# Arrange for guides to be installed with GCC. + +### begin-GG-local: gcc-amigaos +#EXTRA_INSTALL_TARGETS = install-guide install-gcc-amigaos-doc +### end-GG-local + +# Where the guide files go + +guidedir = $(prefix)/guide + +# Actually install guides. + +installdirs-guide: + $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(guidedir) + +install-guide: doc installdirs-guide \ + $(DESTDIR)$(guidedir)/cpp.guide \ + $(DESTDIR)$(guidedir)/gcc.guide \ + $(DESTDIR)$(guidedir)/cppinternals.guide \ + $(DESTDIR)$(guidedir)/gccinstall.guide \ + $(DESTDIR)$(guidedir)/gccint.guide + +$(DESTDIR)$(guidedir)/%.guide: doc/%.guide installdirs-guide + rm -f $@ + if [ -f $< ]; then \ + for f in $(<)*; do \ + realfile=`echo $$f | sed -e 's|.*/\([^/]*\)$$|\1|'`; \ + $(INSTALL_DATA) $$f $(DESTDIR)$(guidedir)/$$realfile; \ + chmod a-x $(DESTDIR)$(guidedir)/$$realfile; \ + done; \ + else true; fi + +### begin-GG-local: gcc-amigaos +# Build and install gcc-amigaos.guide - documentation specific to the +# AmigaOS port of GCC. + +gcc-amigaos-doc:: doc/gcc-amigaos.info doc/gcc-amigaos.guide + +doc/gcc-amigaos.info doc/gcc-amigaos.guide: gcc-amigaos.texi + +install-gcc-amigaos-doc: doc installdirs installdirs-guide \ + $(DESTDIR)$(infodir)/gcc-amigaos.info \ + $(DESTDIR)$(guidedir)/gcc-amigaos.guide +### end-GG-local + +host-amigaos.o : $(srcdir)/config/m68k/host-amigaos.c $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h hosthooks.h hosthooks-def.h toplev.h diagnostic.h + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/m68k/host-amigaos.c diff --git a/gcc/config/m68k/xm-amigaos.h b/gcc/config/m68k/xm-amigaos.h new file mode 100755 index 000000000000..bb571ba040b3 --- /dev/null +++ gcc/config/m68k/xm-amigaos.h @@ -0,0 +1,64 @@ +/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 + Free Software Foundation, Inc. + Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef _FCNTL_H_ +#include +#endif + +/* AmigaOS specific headers, such as from the Native Developer Update kits, + go in SYSTEM_INCLUDE_DIR. STANDARD_INCLUDE_DIR is the equivalent of + Unix "/usr/include". All other include paths are set in Makefile. */ + +#define SYSTEM_INCLUDE_DIR "/gg/os-include" +#define STANDARD_INCLUDE_DIR "/gg/include" + +#define STANDARD_EXEC_PREFIX_1 "/gg/libexec/gcc/" +#define STANDARD_EXEC_PREFIX_2 "/gg/lib/gcc/" +#define STANDARD_STARTFILE_PREFIX_1 "/gg/lib/" +#define STANDARD_STARTFILE_PREFIX_2 "/gg/lib/" + +/* The AmigaOS stores file names with regard to upper/lower case, but actions + on existing files are case independent on the standard filesystems. + + A good example of where this causes problems is the conflict between the C + include file and the C++ include file , where the C++ + include file dir is searched first and thus causes includes of + to include instead. + + In order to solve this problem we define the macro OPEN_CASE_SENSITIVE as + the name of the function that takes the same args as open() and does case + dependent opens. */ + +#define OPEN_CASE_SENSITIVE(NAME, FLAGS, MODE) open ((NAME), (FLAGS) | O_CASE, (MODE)) + +/* On the AmigaOS, there are two pathname separators, '/' (DIR_SEPARATOR) + and ':' (VOL_SEPARATOR). DIR_SEPARATOR defaults to the correct + character, so we don't have to explicitly set it. */ + +#define DIR_SEPARATOR '/' +#define VOL_SEPARATOR ':' +#define DIR_SEPARATOR_2 VOL_SEPARATOR + +/* Zap PREFIX_INCLUDE_DIR, since with the AmigaOS port it is the same as + STANDARD_INCLUDE_DIR. */ + +#undef PREFIX_INCLUDE_DIR diff --git a/gcc/expr.c b/gcc/expr.c index eb77ba0fe533..a2e6a7cac927 100644 --- gcc/expr.c +++ gcc/expr.c @@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" +#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "gimple.h" #include "predict.h" -#include "tm_p.h" #include "ssa.h" #include "expmed.h" #include "optabs.h" diff --git a/gcc/function.c b/gcc/function.c index 401f8f90160d..0c35f094f4cb 100644 --- gcc/function.c +++ gcc/function.c @@ -35,13 +35,13 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" +#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "gimple-expr.h" #include "cfghooks.h" #include "df.h" -#include "tm_p.h" #include "stringpool.h" #include "expmed.h" #include "optabs.h" diff --git a/gcc/ipa-chkp.c b/gcc/ipa-chkp.c index 86c48f14f64d..dc72a5f21021 100644 --- gcc/ipa-chkp.c +++ gcc/ipa-chkp.c @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" +#include "tm_p.h" +#include "target.h" #include "tree.h" #include "gimple.h" #include "tree-pass.h" diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index 4ca2d34607c6..472e203306b8 100644 --- gcc/tree-chkp.c +++ gcc/tree-chkp.c @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" +#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 9f09d30b1f91..149c0c123804 100644 --- gcc/var-tracking.c +++ gcc/var-tracking.c @@ -89,13 +89,13 @@ #include "system.h" #include "coretypes.h" #include "backend.h" +#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "cfghooks.h" #include "alloc-pool.h" #include "tree-pass.h" -#include "tm_p.h" #include "insn-config.h" #include "regs.h" #include "emit-rtl.h" diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index bbbcd5d7ce0c..c8ce02987284 100755 --- libstdc++-v3/configure +++ libstdc++-v3/configure @@ -28820,6 +28820,10 @@ else # Base decisions on target environment. case "${host}" in + m68k-*-*) + # Nothing to do here. + ;; + arm*-*-symbianelf*) # This is a freestanding configuration; there is nothing to do here. ;; From 6951210c6e4901b5e963a19f5cae44bc0560a915 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 15 Dec 2016 00:37:25 +0100 Subject: [PATCH 002/303] @N add .project file --- .project | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .project diff --git a/.project b/.project new file mode 100644 index 000000000000..ab5c4b198d08 --- /dev/null +++ .project @@ -0,0 +1,11 @@ + + + gcc-6 + + + + + + + + From c81713312a097d40d212a5ac5bce13b1aff7b226 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 11 Jan 2017 12:09:34 +0100 Subject: [PATCH 003/303] @B support named sections --- gcc/config/m68k/amigaos.c | 8 ++++++++ gcc/config/m68k/amigaos.h | 17 ++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) mode change 100755 => 100644 gcc/config/m68k/amigaos.c mode change 100755 => 100644 gcc/config/m68k/amigaos.h diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c old mode 100755 new mode 100644 index 90bc3218bab7..facb57a28aa3 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -771,3 +771,11 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, } +/* Output assembly to switch to section NAME with attribute FLAGS. */ + +extern void +amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) +{ + fprintf (asm_out_file, "\t.section\t%s\n", name); +} + diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h old mode 100755 new mode 100644 index 1a33225ab60f..d347a9be63db --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -113,7 +113,15 @@ Boston, MA 02111-1307, USA. */ N_("Restore a4 in all functions") }, \ { "no-always-restore-a4", - MASK_ALWAYS_RESTORE_A4, \ N_("Do not restore a4 in all functions") } - + + +/* Support sections in chip memory, currently '.datachip' only. */ +extern void +amiga_named_section (const char *name, unsigned int flags, tree decl); + +#undef TARGET_ASM_NAMED_SECTION +#define TARGET_ASM_NAMED_SECTION amiga_named_section + #if 0 /* Various ABI issues. */ @@ -139,9 +147,6 @@ Boston, MA 02111-1307, USA. */ #undef PIC_OFFSET_TABLE_REGNUM #define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM) -#undef PIC_REG -#define PIC_REG 12 - /* Use A5 as framepointer instead of A6, since the AmigaOS ABI requires A6 to be used as a shared library base pointer in direct library calls. */ @@ -182,9 +187,7 @@ Boston, MA 02111-1307, USA. */ /* XXX: section support */ #if 0 -/* Support sections in chip memory, currently '.datachip' only. */ -#undef TARGET_ASM_NAMED_SECTION -#define TARGET_ASM_NAMED_SECTION amiga_named_section + /* We define TARGET_ASM_NAMED_SECTION, but we don't support arbitrary sections, including '.gcc_except_table', so we emulate the standard behaviour. */ From 6a04e2c9671b3d0d0de708cd0eb9fdb9bb4d5811 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 12 Jan 2017 00:10:47 +0100 Subject: [PATCH 004/303] @B fix null ptr --- gcc/config/m68k/amigaos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index facb57a28aa3..8727c7184812 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -508,7 +508,7 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) /* FIXME: Two last conditions below are workarounds for bugs. */ else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode) { - if (POINTER_TYPE_P(type)) + if (!type || POINTER_TYPE_P(type)) regbegin = 8; /* Ax */ else regbegin = 0; /* Dx */ From 09a2cda05b28a749e39d8e0af34ef3556eb21d6a Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 12 Jan 2017 00:12:11 +0100 Subject: [PATCH 005/303] @I added quirky -fbaserel -fbaserel32 - really working? nut sure... --- gcc/config/m68k/amigaos.h | 2 +- gcc/config/m68k/amigaos.opt | 7 +++++++ gcc/config/m68k/m68k.c | 20 +++++++++++--------- 3 files changed, 19 insertions(+), 10 deletions(-) mode change 100755 => 100644 gcc/config/m68k/amigaos.opt diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index d347a9be63db..fd89bb34352c 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -471,7 +471,7 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*); #define SUBTARGET_OVERRIDE_OPTIONS \ do \ { \ - if (!TARGET_68020 && flag_pic==4) \ + if (!TARGET_68020 && flag_pic==2) \ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \ diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt old mode 100755 new mode 100644 index a9bc80c4f5b6..4298bc90abe1 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -11,3 +11,10 @@ msmall-code Target RejectNegative small code model +fbaserel +Target Common Report Var(flag_pic,3) Negative(fpie) Init(-1) +Backward compatibility, use -fpic now + +fbaserel32 +Target Common Report Var(flag_pic,4) Negative(fPIE) Init(-1) +Backward compatibility, use -fPIC now \ No newline at end of file diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index fe3a939e1530..ce28681c1dc9 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -557,7 +557,7 @@ m68k_option_override (void) : (m68k_cpu_flags & FL_COLDFIRE) != 0 ? FPUTYPE_COLDFIRE : FPUTYPE_68881); - /* Sanity check to ensure that msep-data and mid-sahred-library are not + /* Sanity check to ensure that msep-data and mid-shared-library are not * both specified together. Doing so simply doesn't make sense. */ if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY) @@ -568,7 +568,7 @@ m68k_option_override (void) * -fpic but it hasn't been tested properly. */ if (TARGET_SEP_DATA || TARGET_ID_SHARED_LIBRARY) - flag_pic = 2; + flag_pic = TARGET_68020 ? 2 : 1; /* -mpcrel -fPIC uses 32-bit pc-relative displacements. Raise an error if the target does not support them. */ @@ -1139,9 +1139,9 @@ m68k_expand_prologue (void) current_frame.reg_mask, true, true)); } - if (!TARGET_SEP_DATA - && crtl->uses_pic_offset_table) - emit_insn (gen_load_got (pic_offset_table_rtx)); +// if (!TARGET_SEP_DATA +// && crtl->uses_pic_offset_table) +// emit_insn (gen_load_got (pic_offset_table_rtx)); } /* Return true if a simple (return) instruction is sufficient for this @@ -4693,8 +4693,10 @@ print_operand_address (FILE *file, rtx addr) { struct m68k_address address; - if (!m68k_decompose_address (QImode, addr, true, &address)) + if (!m68k_decompose_address (QImode, addr, true, &address)) { + debug_rtx(addr); gcc_unreachable (); + } if (address.code == PRE_DEC) fprintf (file, MOTOROLA ? "-(%s)" : "%s@-", @@ -4719,7 +4721,7 @@ print_operand_address (FILE *file, rtx addr) /* (d16,PC) or (bd,PC,Xn) (with suppressed index register). */ fputc ('(', file); output_addr_const (file, addr); - asm_fprintf (file, flag_pic == 1 ? ":w,%Rpc)" : ":l,%Rpc)"); + asm_fprintf (file, flag_pic == 1 || flag_pic == 3 ? ":w,%Rpc)" : ":l,%Rpc)"); } else { @@ -5124,8 +5126,8 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, /* Use the static chain register as a temporary (call-clobbered) GOT pointer for this function. We can use the static chain register because it isn't live on entry to the thunk. */ - SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM); - emit_insn (gen_load_got (pic_offset_table_rtx)); +// SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM); +// emit_insn (gen_load_got (pic_offset_table_rtx)); } legitimize_pic_address (XEXP (mem, 0), Pmode, tmp); mem = replace_equiv_address (mem, tmp); From e807bcc3fe2a83cc3b617c78c7f81685e861b5d1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 12 Jan 2017 00:20:27 +0100 Subject: [PATCH 006/303] @I --- gcc/config/m68k/amigaos.c | 0 gcc/config/m68k/amigaos.h | 0 gcc/config/m68k/amigaos.opt | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gcc/config/m68k/amigaos.c mode change 100644 => 100755 gcc/config/m68k/amigaos.h mode change 100644 => 100755 gcc/config/m68k/amigaos.opt diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c old mode 100644 new mode 100755 diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h old mode 100644 new mode 100755 diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt old mode 100644 new mode 100755 From 79e34a64428598cfb90bdf9f67aa32ad8c02effb Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 12 Jan 2017 00:21:21 +0100 Subject: [PATCH 007/303] Revert "@I" This reverts commit e807bcc3fe2a83cc3b617c78c7f81685e861b5d1. --- gcc/config/m68k/amigaos.c | 0 gcc/config/m68k/amigaos.h | 0 gcc/config/m68k/amigaos.opt | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 gcc/config/m68k/amigaos.c mode change 100755 => 100644 gcc/config/m68k/amigaos.h mode change 100755 => 100644 gcc/config/m68k/amigaos.opt diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c old mode 100755 new mode 100644 diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h old mode 100755 new mode 100644 diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt old mode 100755 new mode 100644 From 010fd69732e88d124686e46202f7a26bc9fa77ec Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 12 Jan 2017 15:13:10 +0100 Subject: [PATCH 008/303] @B fix endless option parsing loop --- gcc/config/m68k/amigaos.opt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 4298bc90abe1..f933fe29b98b 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -12,9 +12,9 @@ Target RejectNegative small code model fbaserel -Target Common Report Var(flag_pic,3) Negative(fpie) Init(-1) +Target Common Report Var(flag_pic,3) Init(-1) Backward compatibility, use -fpic now fbaserel32 -Target Common Report Var(flag_pic,4) Negative(fPIE) Init(-1) +Target Common Report Var(flag_pic,4) Init(-1) Backward compatibility, use -fPIC now \ No newline at end of file From c8b17fa2d8719ce6efc9535408966cd7ce87e2b8 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 31 Jan 2017 20:42:38 +0100 Subject: [PATCH 009/303] @N re-added old target options, @R -fbaserel seems to work --- gcc/config/m68k/amigaos.c | 7 +- gcc/config/m68k/amigaos.opt | 20 ++- gcc/config/m68k/m68k.c | 30 +++-- gcc/config/m68k/m68kamigaos.h | 283 ++++++++++++++++++++++++++++++++---------- 4 files changed, 257 insertions(+), 83 deletions(-) mode change 100755 => 100644 gcc/config/m68k/m68kamigaos.h diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 8727c7184812..19b0f5b4cc82 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -41,6 +41,8 @@ Boston, MA 02111-1307, USA. */ #include "config/m68k/amigaos.h" +//int amiga_declare_object; + #if 0 static int amigaos_put_in_text (tree); static rtx gen_stack_management_call (rtx, rtx, const char *); @@ -776,6 +778,9 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, extern void amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) { - fprintf (asm_out_file, "\t.section\t%s\n", name); + if (0 == strncmp(".text", name, 5)) + name = ".text"; +// fprintf (asm_out_file, "\t.section\t%s\n", name); + fprintf (asm_out_file, "\t%s\n", name); } diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index f933fe29b98b..29a3688470d0 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -12,9 +12,21 @@ Target RejectNegative small code model fbaserel -Target Common Report Var(flag_pic,3) Init(-1) -Backward compatibility, use -fpic now +Target Common Report Var(flag_mybaserel,1) +data is adressed relativ to a4 fbaserel32 -Target Common Report Var(flag_pic,4) Init(-1) -Backward compatibility, use -fPIC now \ No newline at end of file +Target Common Report Var(flag_mybaserel,2) +data is adressed relativ to a4 with 32 bit offsets + +resident +Target Common Report Var(flag_mybaserel,1) +data is adressed relativ to a4, linked as resident + +resident32 +Target Common Report Var(flag_mybaserel,2) +data is adressed relativ to a4 with 32 bit offsets, linked as resident + +mcrt= +Target RejectNegative Var(amigaos_crt) Joined +Specify startup binary \ No newline at end of file diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index ce28681c1dc9..387f0c1b9e02 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -1139,9 +1139,9 @@ m68k_expand_prologue (void) current_frame.reg_mask, true, true)); } -// if (!TARGET_SEP_DATA -// && crtl->uses_pic_offset_table) -// emit_insn (gen_load_got (pic_offset_table_rtx)); + if (!TARGET_SEP_DATA + && crtl->uses_pic_offset_table) + emit_insn (gen_load_got (pic_offset_table_rtx)); } /* Return true if a simple (return) instruction is sufficient for this @@ -4496,7 +4496,10 @@ print_operand (FILE *file, rtx op, int letter) && !(GET_CODE (XEXP (op, 0)) == CONST_INT && INTVAL (XEXP (op, 0)) < 0x8000 && INTVAL (XEXP (op, 0)) >= -0x8000)) - fprintf (file, MOTOROLA ? ".l" : ":l"); +#ifdef TARGET_AMIGA + if (!flag_mybaserel) +#endif + fprintf (file, MOTOROLA ? ".l" : ":l"); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) { @@ -4693,10 +4696,8 @@ print_operand_address (FILE *file, rtx addr) { struct m68k_address address; - if (!m68k_decompose_address (QImode, addr, true, &address)) { - debug_rtx(addr); + if (!m68k_decompose_address (QImode, addr, true, &address)) gcc_unreachable (); - } if (address.code == PRE_DEC) fprintf (file, MOTOROLA ? "-(%s)" : "%s@-", @@ -4721,7 +4722,7 @@ print_operand_address (FILE *file, rtx addr) /* (d16,PC) or (bd,PC,Xn) (with suppressed index register). */ fputc ('(', file); output_addr_const (file, addr); - asm_fprintf (file, flag_pic == 1 || flag_pic == 3 ? ":w,%Rpc)" : ":l,%Rpc)"); + asm_fprintf (file, flag_pic == 1 ? ":w,%Rpc)" : ":l,%Rpc)"); } else { @@ -4738,6 +4739,15 @@ print_operand_address (FILE *file, rtx addr) } else output_addr_const (file, addr); + + if (!RTX_FLAG (addr, frame_related)) + { +// debug_rtx(addr); + if (flag_mybaserel == 1) + asm_fprintf (file, ".w(a4)"); + else if (flag_mybaserel == 2) + asm_fprintf (file, "(a4)"); + } } } else @@ -5126,8 +5136,8 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, /* Use the static chain register as a temporary (call-clobbered) GOT pointer for this function. We can use the static chain register because it isn't live on entry to the thunk. */ -// SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM); -// emit_insn (gen_load_got (pic_offset_table_rtx)); + SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM); + emit_insn (gen_load_got (pic_offset_table_rtx)); } legitimize_pic_address (XEXP (mem, 0), Pmode, tmp); mem = replace_equiv_address (mem, tmp); diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h old mode 100755 new mode 100644 index 0ce599138c7d..df0ce5b52ede --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #define TARGET_AMIGA 1 #endif +#define HAS_INIT_SECTION + #ifndef SWBEG_ASM_OP #define SWBEG_ASM_OP "\t.swbeg\t" #endif @@ -88,6 +90,28 @@ do { \ fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \ } while (0) +#if 0 +extern int amiga_declare_object; + +#define ASM_DECLARE_OBJECT_NAME(FILE,NAME,DECL) \ +if (!DECL_INITIAL (DECL) || \ + initializer_zerop (DECL_INITIAL (decl))) \ + { \ + amiga_declare_object = 1; \ + fprintf ((FILE), ".comm\t%s,", NAME); \ + } \ +else \ +ASM_OUTPUT_LABEL (FILE, NAME) + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ +if (amiga_declare_object) \ + fprintf (FILE, "%u\n", (int)(SIZE)); \ +else \ + fprintf (FILE, "\t.skip %u\n", (int)(SIZE)); \ +amiga_declare_object = 0 +#endif + /* Register in which address to store a structure value is passed to a function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */ @@ -145,14 +169,8 @@ do { \ fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); /* end of stuff from m68kv4.h */ -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s" - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crtbegin.o%s" - #ifndef BSS_SECTION_ASM_OP -#define BSS_SECTION_ASM_OP "\t.section\t.bss" +#define BSS_SECTION_ASM_OP "\t.bss" #endif #ifndef ASM_OUTPUT_ALIGNED_BSS @@ -168,8 +186,6 @@ do { \ provided for compatibility reasons. When creating shared libraries, use different 'errno'. */ - - #undef TARGET_OS_CPP_BUILTINS #define TARGET_OS_CPP_BUILTINS() \ do \ @@ -178,8 +194,8 @@ do { \ builtin_define ("__saveds=__attribute__((__saveds__))"); \ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \ builtin_define ("__stackext=__attribute__((__stackext__))"); \ - builtin_define ("__regargs_x=__attribute__((regparm))"); \ - builtin_define ("__stdargs_x=__attribute__((stkparm))"); \ + builtin_define ("__regargs=__attribute__((regparm))"); \ + builtin_define ("__stdargs=__attribute__((stkparm))"); \ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \ builtin_define_std ("amiga"); \ builtin_define_std ("amigaos"); \ @@ -195,6 +211,11 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #endif +/* put return values in FPU build in FP0 Reg */ +#undef FUNCTION_VALUE_REGNO_P +#define FUNCTION_VALUE_REGNO_P(N) \ + ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG)) + /* Inform the program which CPU we compile for. */ //#undef TARGET_CPU_CPP_BUILTINS @@ -229,14 +250,27 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ } \ while (0) */ + +/* When creating shared libraries, use different 'errno'. */ +#define CPP_IXEMUL_SPEC \ + "%{!ansi:-Dixemul} -D__ixemul__ -D__ixemul " \ + "%{malways-restore-a4:-Derrno=(*ixemul_errno)} " \ + "%{mrestore-a4:-Derrno=(*ixemul_errno)}" +#define CPP_LIBNIX_SPEC \ + "-isystem %(sdk_root)libnix/include " \ + "%{!ansi:-Dlibnix} -D__libnix__ -D__libnix" +#define CPP_CLIB2_SPEC \ + "-isystem %(sdk_root)clib2/include " \ + "%{!ansi:-DCLIB2} -D__CLIB2__ -D__CLIB2" + /* Define __HAVE_68881__ in preprocessor according to the -m flags. This will control the use of inline 68881 insns in certain macros. Note: it should be set in TARGET_CPU_CPP_BUILTINS but TARGET_68881 isn't the same -m68881 since its also true for -m680[46]0 ... Differentiate between libnix and ixemul. */ -#define CPP_SPEC \ - "%{m68881:-D__HAVE_68881__} " \ +#define CPP_SPEC \ + "%{m68881:-D__HAVE_68881__} " \ "%{!ansi:" \ "%{m68020:-Dmc68020} " \ "%{mc68020:-Dmc68020} " \ @@ -252,16 +286,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{m68030:-D__mc68030__ -D__mc68030} " \ "%{m68040:-D__mc68040__ -D__mc68040} " \ "%{m68060:-D__mc68060__ -D__mc68060} " \ - "%{noixemul:%{!ansi:%{!std=*:-Dlibnix}%{std=gnu*:-Dlibnix}} -D__libnix -D__libnix__} " \ - "%{!noixemul:%{!ansi:%{!std=*:-Dixemul}%{std=gnu*:-Dixemul}} -D__ixemul -D__ixemul__}" - -/* Translate '-resident' to '-fbaserel' (they differ in linking stage only). - Don't put function addresses in registers for PC-relative code. */ - -#define CC1_SPEC \ - "%{resident:-fbaserel} " \ - "%{resident32:-fbaserel32} " \ - "%{msmall-code:-fno-function-cse}" + "%{noixemul:%(cpp_libnix)} " \ + "%{mcrt=nix*:%(cpp_libnix)} " \ + "%{mcrt=ixemul:%(cpp_ixemul)} " \ + "%{mcrt=clib2:%(cpp_clib2)}" /* Various -m flags require special flags to the assembler. */ @@ -280,48 +308,56 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #define ASM_CPU_DEFAULT_SPEC \ "%{!m680*:%{!mc680*:-m68040}}" -/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD - compatible debug hunk. - Also, pass appropriate linker flavours depending on user-supplied - commandline options. */ - -#define LINK_SPEC \ - "%{noixemul:-fl libnix} " \ - "%{resident*:-amiga-datadata-reloc} " \ - "%{resident|fbaserel:-m amiga_bss -fl libb} " \ - "%{resident32|fbaserel32:-m amiga_bss -fl libb32} " \ - "%{g:-amiga-debug-hunk} " \ - "%(link_cpu)" - -#define LINK_CPU_SPEC \ - "%{m6802*|mc68020|m68030|m68040|m68060:-fl libm020} " \ - "%{m68881:-fl libm881}" - /* Choose the right startup file, depending on whether we use base relative code, base relative code with automatic relocation (-resident), their 32-bit versions, libnix, profiling or plain crt0.o. */ -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!noixemul:" \ - "%{fbaserel:%{!resident:bcrt0.o%s}}" \ - "%{resident:rcrt0.o%s}" \ - "%{fbaserel32:%{!resident32:lcrt0.o%s}}" \ - "%{resident32:scrt0.o%s}" \ - "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \ - "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}}" \ - "%{noixemul:" \ - "%{resident:libnix/nrcrt0.o%s} " \ - "%{!resident:%{fbaserel:libnix/nbcrt0.o%s}%{!fbaserel:libnix/ncrt0.o%s}}}" +#define STARTFILE_IXEMUL_SPEC \ + "%{fbaserel:%{!resident:bcrt0.o%s}}" \ + "%{resident:rcrt0.o%s}" \ + "%{fbaserel32:%{!resident32:lcrt0.o%s}}" \ + "%{resident32:scrt0.o%s}" \ + "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \ + "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}" +#define STARTFILE_LIBNIX_SPEC \ + "%(sdk_root)lib/libnix/" \ + "%{ramiga-*:" \ + "%{ramiga-lib:libinit.o%s}" \ + "%{ramiga-libr:libinitr.o%s}" \ + "%{ramiga-dev:devinit.o%s}}" \ + "%{!ramiga-*:" \ + "%{resident:nrcrt0.o%s}" \ + "%{!resident:" \ + "%{fbaserel:nbcrt0.o%s}" \ + "%{!fbaserel:ncrt0.o%s}}}" +#define STARTFILE_CLIB2_SPEC \ + "%(sdk_root)clib2/lib/" \ + "%{resident32:nr32crt0.o%s}" \ + "%{!resident32:" \ + "%{fbaserel32:nb32crt0.o%s}" \ + "%{!fbaserel32:" \ + "%{resident:nrcrt0.o%s}" \ + "%{!resident:" \ + "%{fbaserel:nbcrt0.o%s}" \ + "%{!fbaserel:ncrt0.o%s}}}}" -#undef ENDFILE_SPEC -#define ENDFILE_SPEC \ - "%{noixemul:-lstubs}" +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{noixemul:%(startfile_libnix)} " \ + "%{mcrt=nix*:%(startfile_libnix)} " \ + "%{mcrt=ixemul:%(startfile_ixemul)} " \ + "%{mcrt=clib2:%(startfile_clib2)}" -/* put return values in FPU build in FP0 Reg */ -#undef FUNCTION_VALUE_REGNO_P -#define FUNCTION_VALUE_REGNO_P(N) \ - ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG)) +#define ENDFILE_IXEMUL_SPEC "" +#define ENDFILE_LIBNIX_SPEC "-lstubs" +#define ENDFILE_CLIB2_SPEC "" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{noixemul:%(endfile_libnix)} " \ + "%{mcrt=nix*:%(endfile_libnix)} " \ + "%{mcrt=ixemul:%(endfile_ixemul)} " \ + "%{mcrt=clib2:%(endfile_clib2)}" /* Automatically search libamiga.a for AmigaOS specific functions. Note @@ -337,13 +373,106 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ to put in a -lamiga himself and get it in the wrong place, so that (for example) calls like sprintf come from -lamiga rather than -lc. */ -#undef LIB_SPEC -#define LIB_SPEC \ - "%{!noixemul:" \ - "%{p|pg:-lc_p}" \ - "%{!p:%{!pg:-lc -lamiga -lc}}}" \ - "%{noixemul:" \ - "-lnixmain -lnix -lamiga %{mstackcheck|mstackextend:-lstack}}" +#define LIB_IXEMUL_SPEC \ + "%{!p:%{!pg:-lc -lamiga -lc}} " \ + "%{p:-lc_p} %{pg:-lc_p}" +#define LIB_LIBNIX_SPEC \ + "-lnixmain -lnix -lstubs " \ + "%{mcrt=*:-l%*} " \ + "%{!mcrt=*:-lnix20} " \ + "-lamiga " \ + "%{mstackcheck:-lstack} " \ + "%{mstackextend:-lstack}" +#define LIB_CLIB2_SPEC \ + "-lc -lamiga -ldebug " \ + "%{mstackcheck:-lstack} " \ + "%{mstackextend:-lstack}" + +#define LIB_SPEC \ + "%{noixemul:%(lib_libnix)} " \ + "%{mcrt=nix*:%(lib_libnix)} " \ + "%{mcrt=ixemul:%(lib_ixemul)} " \ + "%{mcrt=clib2:%(lib_clib2)}" + +#define LIBGCC_IXEMUL_SPEC "" +#define LIBGCC_LIBNIX_SPEC "-lnix " \ + "%{mcrt=*:-l%*} " \ + "%{!mcrt=*:-lnix20}" +#define LIBGCC_CLIB2_SPEC "-lc" +//#define LIBGCC_SPEC "-lgcc " +#define LIBGCC_SPEC " " \ + "%{noixemul:%(libgcc_libnix)} " \ + "%{mcrt=nix*:%(libgcc_libnix)} " \ + "%{mcrt=ixemul:%(libgcc_ixemul)} " \ + "%{mcrt=clib2:%(libgcc_clib2)}" + +/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD + compatible debug hunk. + Also, pass appropriate linker flavours depending on user-supplied + commandline options. */ + +#define LINK_IXEMUL_SPEC "" +#define LINK_LIBNIX_SPEC "-L%(sdk_root)libnix/lib -fl libnix" +#define LINK_CLIB2_SPEC "-L%(sdk_root)clib2/lib" + +/* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD + compatible debug hunk. + Also, pass appropriate linker flavours depending on user-supplied + commandline options. */ + +#define LINK_SPEC \ + "%{noixemul:%(link_libnix)} " \ + "%{mcrt=nix*:%(link_libnix)} " \ + "%{mcrt=ixemul:%(link_ixemul)} " \ + "%{mcrt=clib2:%(link_clib2)} " \ + "%{fbaserel:%{!resident:-m amiga_bss -fl libb}} " \ + "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb} " \ + "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \ + "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \ + "%{g:-amiga-debug-hunk} " \ + "%{m68020:-fl libm020} " \ + "%{mc68020:-fl libm020} " \ + "%{m68030:-fl libm020} " \ + "%{m68040:-fl libm020} " \ + "%{m68060:-fl libm020} " \ + "%{m68020-40:-fl libm020} " \ + "%{m68020-60:-fl libm020} " \ + "%{m68881:-fl libm881}" + +/* Translate '-resident' to '-fbaserel' (they differ in linking stage only). + Don't put function addresses in registers for PC-relative code. */ + +#define CC1_SPEC \ + "%{resident:-fbaserel} " \ + "%{resident32:-fbaserel32} " \ + "%{msmall-code:-fno-function-cse}" + +#define LINK_CPU_SPEC \ + "%{m6802*|mc68020|m68030|m68040|m68060:-fl libm020} " \ + "%{m68881:-fl libm881}" + +/* [cahirwpz] A modified copy of LINK_COMMAND_SPEC from gcc/gcc.c file. + Don't prepend libgcc.a to link libraries and make sure the options is + at the end of command line. Otherwise linker chooses generic functions + from libgcc.a instead AmigaOS-specific counterparts from libnix.a. */ + +#define LINK_COMMAND_SPEC \ + "%{!fsyntax-only:" \ + "%{!c:" \ + "%{!M:" \ + "%{!MM:" \ + "%{!E:" \ + "%{!S:" \ + "%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} " \ + "%{N} %{n} %{r} %{s} %{t} %{u*} %{x} %{z} %{Z} " \ + "%{!A:%{!nostdlib:%{!nostartfiles:%S}}} " \ + "%{static:} %{L*} %D %o " \ + "%{!nostdlib:%{!nodefaultlibs:%L}} " \ + "%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \ + "%{!nostdlib:%{!nodefaultlibs:%G}} " \ + "%{T*} }}}}}} " \ + + /* This macro defines names of additional specifications to put in the specs that can be used in various specifications like CC1_SPEC. Its definition @@ -358,8 +487,26 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #define EXTRA_SPECS \ { "asm_cpu", ASM_CPU_SPEC }, \ { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \ - { "link_cpu", LINK_CPU_SPEC } - + { "link_cpu", LINK_CPU_SPEC }, \ + {"sdk_root", TOOLDIR_BASE_PREFIX "m68k-amigaos/"}, \ + {"cpp_ixemul", CPP_IXEMUL_SPEC}, \ + {"cpp_libnix", CPP_LIBNIX_SPEC}, \ + {"cpp_clib2", CPP_CLIB2_SPEC}, \ + {"lib_ixemul", LIB_IXEMUL_SPEC}, \ + {"lib_libnix", LIB_LIBNIX_SPEC}, \ + {"lib_clib2", LIB_CLIB2_SPEC}, \ + {"link_ixemul", LINK_IXEMUL_SPEC}, \ + {"link_libnix", LINK_LIBNIX_SPEC}, \ + {"link_clib2", LINK_CLIB2_SPEC}, \ + {"startfile_ixemul", STARTFILE_IXEMUL_SPEC}, \ + {"startfile_libnix", STARTFILE_LIBNIX_SPEC}, \ + {"startfile_clib2", STARTFILE_CLIB2_SPEC}, \ + {"endfile_ixemul", ENDFILE_IXEMUL_SPEC}, \ + {"endfile_libnix", ENDFILE_LIBNIX_SPEC}, \ + {"endfile_clib2", ENDFILE_CLIB2_SPEC}, \ + {"libgcc_ixemul", LIBGCC_IXEMUL_SPEC}, \ + {"libgcc_libnix", LIBGCC_LIBNIX_SPEC}, \ + {"libgcc_clib2", LIBGCC_CLIB2_SPEC} /* begin-GG-local: dynamic libraries */ From d1df1ebb0f08f356222c21b1744476eb881b3b0c Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 1 Feb 2017 11:40:21 +0100 Subject: [PATCH 010/303] @B mregparm was always enabled with 2 registers. Now it's off. --- gcc/config/m68k/amigaos.c | 30 ++++++++++++++++++------------ gcc/config/m68k/amigaos.opt | 2 +- gcc/config/m68k/m68k.c | 11 ++++++----- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 19b0f5b4cc82..e2dd5bab75f9 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -40,6 +40,12 @@ Boston, MA 02111-1307, USA. */ #include "diagnostic-core.h" #include "config/m68k/amigaos.h" +//#define MYDEBUG 1 +#ifdef MYDEBUG +#define DPRINTF(x) printf x; fflush(stdout); +#else +#define DPRINTF(x) +#endif //int amiga_declare_object; @@ -379,8 +385,8 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype) { struct amigaos_args * cum = &mycum; lastcum = cump; - cum->num_of_regs = amigaos_regparm; -// printf("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs); fflush(stdout); + cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; + DPRINTF(("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. @@ -396,7 +402,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype) else { tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES(fntype)); - cum->num_of_regs = amigaos_regparm ? + cum->num_of_regs = amigaos_regparm != 0 ? amigaos_regparm : AMIGAOS_DEFAULT_REGPARM; if (ratree) { @@ -456,7 +462,7 @@ amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v); /* Update the data in CUM to advance over an argument. */ - // printf("amigaos_function_arg_advance1 %p\r\n", cump); fflush(stdout); + DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump)); if (cump != lastcum) return; @@ -490,7 +496,7 @@ static struct rtx_def * _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) { struct amigaos_args * cum = &mycum; - // printf("m68k_function_arg numOfRegs=%p\r\n", cum); + DPRINTF(("m68k_function_arg numOfRegs=%d\r\n", cum ? cum->num_of_regs : 0)); if (cump != lastcum) return 0; @@ -550,7 +556,7 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) if (cum->last_arg_reg != -1) { - // printf("-> gen_rtx_REG %d\r\n", cum->last_arg_reg); + DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg)); return gen_rtx_REG (mode, cum->last_arg_reg); } } @@ -566,7 +572,7 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, { struct amigaos_args * cum = &mycum; - // printf("amigaos_function_arg %p\r\n", cum_v.p); fflush(stdout); + DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p)); CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v); @@ -598,7 +604,7 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, int amigaos_comp_type_attributes (const_tree type1, const_tree type2) { - printf("amigaos_comp_type_attributes\n"); + DPRINTF(("amigaos_comp_type_attributes\n")); /* Functions or methods are incompatible if they specify mutually exclusive ways of passing arguments. */ if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE) @@ -688,7 +694,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, { tree nnn = *node; do { // while (0); -// printf("%p with treecode %d\n", node, TREE_CODE(nnn)); fflush(stdout); + DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn))); if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE || TREE_CODE (nnn) == METHOD_TYPE) { @@ -696,7 +702,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, single class that should be used to pass arguments. */ if (is_attribute_p ("regparm", name)) { -// printf ("regparm found\n"); fflush(stdout); + DPRINTF(("regparm found\n")); if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn))) { @@ -706,7 +712,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, if (args && TREE_CODE (args) == TREE_LIST) { tree val = TREE_VALUE(args); -// printf ("regparm with val: %d\n", TREE_CODE(val)); + DPRINTF(("regparm with val: %d\n", TREE_CODE(val))); if (TREE_CODE (val) == INTEGER_CST) { int no = TREE_INT_CST_LOW(val); @@ -765,7 +771,7 @@ bool amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed) { -// printf("outer: %d, opno: %d", outer_code, opno); fflush(stdout); + DPRINTF(("outer: %d, opno: %d", outer_code, opno)); // debug_rtx(x); bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); *total *= 4; diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 29a3688470d0..212ab8e6efda 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -1,6 +1,6 @@ mregparm= -Target RejectNegative Var(amigaos_regparm) Joined UInteger +Target RejectNegative Var(amigaos_regparm) Joined UInteger Init(-1) Pass arguments through registers. noixemul diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 387f0c1b9e02..3ebc9020c4e0 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -166,7 +166,7 @@ static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); static bool m68k_ok_for_sibcall_p (tree, tree); static bool m68k_tls_symbol_p (rtx); static rtx m68k_legitimize_address (rtx, rtx, machine_mode); -#ifndef TARGET_AMIGAOS +#ifndef TARGET_AMIGA static #endif bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); @@ -2803,7 +2803,7 @@ const_int_cost (HOST_WIDE_INT i) } } -#ifndef TARGET_AMIGAOS +#ifndef TARGET_AMIGA static #endif bool @@ -4544,9 +4544,10 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc) switch (reloc) { case RELOC_GOT: - if (TARGET_AMIGAOS) - return ""; - else if (MOTOROLA) +// if (TARGET_AMIGA) +// return ""; +// else + if (MOTOROLA) { if (flag_pic == 1 && TARGET_68020) return "@GOT.w"; From 0a6678c57629151eaec736ce82fa69dcc4e08c53 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 9 Feb 2017 22:01:27 +0100 Subject: [PATCH 011/303] @B select correct crt0 file with baserel32 --- gcc/config/m68k/m68kamigaos.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index df0ce5b52ede..0650102861e8 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -329,7 +329,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{resident:nrcrt0.o%s}" \ "%{!resident:" \ "%{fbaserel:nbcrt0.o%s}" \ - "%{!fbaserel:ncrt0.o%s}}}" + "%{!fbaserel:" \ + "%{fbaserel32:nlbcrt0.o%s}" \ + "%{!fbaserel32:ncrt0.o%s}}}}" + #define STARTFILE_CLIB2_SPEC \ "%(sdk_root)clib2/lib/" \ "%{resident32:nr32crt0.o%s}" \ @@ -430,6 +433,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \ "%{g:-amiga-debug-hunk} " \ + "%{mcpu=68020:-fl libm020} " \ "%{m68020:-fl libm020} " \ "%{mc68020:-fl libm020} " \ "%{m68030:-fl libm020} " \ From 38ec4180a5c5d9d7a87725d347838f3b55f837fa Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 9 Feb 2017 22:02:40 +0100 Subject: [PATCH 012/303] @B -m68881 is not longer enabled by default for -m68020 --- gcc/config/m68k/m68k.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 3ebc9020c4e0..c67194fa292d 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -352,11 +352,21 @@ struct gcc_target targetm = TARGET_INITIALIZER; /* Base flags for 68k ISAs. */ #define FL_FOR_isa_00 FL_ISA_68000 #define FL_FOR_isa_10 (FL_FOR_isa_00 | FL_ISA_68010) -/* FL_68881 controls the default setting of -m68881. gcc has traditionally +/* "FL_68881 controls the default setting of -m68881. gcc has traditionally generated 68881 code for 68020 and 68030 targets unless explicitly told - not to. */ + not to." + + This is not true at least for the AMIGA. + gcc 2.93 does not set the 68881 flag. + + */ +#ifdef TARGET_AMIGA +#define FL_FOR_isa_20 (FL_FOR_isa_10 | FL_ISA_68020 \ + | FL_BITFIELD | FL_CAS) +#else #define FL_FOR_isa_20 (FL_FOR_isa_10 | FL_ISA_68020 \ | FL_BITFIELD | FL_68881 | FL_CAS) +#endif #define FL_FOR_isa_40 (FL_FOR_isa_20 | FL_ISA_68040) #define FL_FOR_isa_cpu32 (FL_FOR_isa_10 | FL_ISA_68020) From 5d9da9f9a2d9fec32fba2b7b9f2326d1f1c4f1f0 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 9 Feb 2017 22:05:42 +0100 Subject: [PATCH 013/303] @R added a hack to support multiline __asm("...") statements --- gcc/c/c-parser.c | 7 +++++++ libcpp/lex.c | 23 ++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index d8725b572b55..cde6fe0c1c59 100644 --- gcc/c/c-parser.c +++ gcc/c/c-parser.c @@ -3908,6 +3908,7 @@ c_parser_asm_string_literal (c_parser *parser) static tree c_parser_simple_asm_expr (c_parser *parser) { + extern int in_assembler_directive; tree str; gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM)); /* ??? Follow the C++ parser rather than using the @@ -3919,7 +3920,13 @@ c_parser_simple_asm_expr (c_parser *parser) parser->lex_untranslated_string = false; return NULL_TREE; } + + // SBF: set in_assembler_directive to enable multi-line strings. And yes, it's a HACK. + in_assembler_directive = 1; str = c_parser_asm_string_literal (parser); + // SBF: in_assembler_directive disabled + in_assembler_directive = 0; + parser->lex_untranslated_string = false; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) { diff --git a/libcpp/lex.c b/libcpp/lex.c index e5a0397f3099..c2131adeb38e 100644 --- libcpp/lex.c +++ libcpp/lex.c @@ -64,6 +64,10 @@ static tokenrun *next_tokenrun (tokenrun *); static _cpp_buff *new_buff (size_t); +/* + * SBF: This flag is set if an asm statement is parsed, to support multiline strings in __asm() + */ +int in_assembler_directive; /* Utility routine: @@ -1063,7 +1067,10 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment) else if (note->type == 0) /* Already processed in lex_raw_string. */; else - abort (); + { +// abort (); + printf("ups: note type=%d\n", note->type); + } } } @@ -1875,6 +1882,20 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) break; else if (c == '\n') { + /* + * SBF: allow multi-line strings + * Ignore the line end and move to next line. + * Only fail, if there is no next line + */ + if (in_assembler_directive) + { + cpp_buffer *buffer = pfile->buffer; + if (buffer->cur < buffer->rlimit) + CPP_INCREMENT_LINE (pfile, 0); + buffer->need_line = true; + if (_cpp_get_fresh_line (pfile)) + continue; + } cur--; /* Unmatched quotes always yield undefined behavior, but greedy lexing means that what appears to be an unterminated From 6515b7470c3baf385a0dca132bc1c71acbcdda5f Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 12 Feb 2017 12:40:37 +0100 Subject: [PATCH 014/303] @R allow used registers inside of the clobber list --- gcc/cfgexpand.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index b612293b1a7a..4215ae90c63d 100644 --- gcc/cfgexpand.c +++ gcc/cfgexpand.c @@ -2732,6 +2732,10 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs) { /* Conflicts between asm-declared register variables and the clobber list are not allowed. */ + /* + * SBF: Why? + */ +#ifndef TARGET_AMIGA tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs); if (overlap) @@ -2744,7 +2748,7 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs) DECL_REGISTER (overlap) = 0; return true; } - +#endif return false; } @@ -3255,11 +3259,15 @@ expand_asm_stmt (gasm *stmt) if (reg_overlap_mentioned_p (clobbered_reg, output_rvec[k])) internal_error ("asm clobber conflict with output operand"); +/** + * SBF: Why? + */ +#ifndef TARGET_AMIGA for (unsigned k = 0; k < ninputs - ninout; ++k) if (reg_overlap_mentioned_p (clobbered_reg, input_rvec[k])) internal_error ("asm clobber conflict with input operand"); +#endif } - XVECEXP (body, 0, i++) = gen_rtx_CLOBBER (VOIDmode, clobbered_reg); } From 7de2f3e6f2786a6d5e789230227f9d7c5f3e2316 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 12 Feb 2017 12:41:09 +0100 Subject: [PATCH 015/303] @B fix mixing struct/class for the same class. --- gcc/coretypes.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 12067fdf5348..f0f069f6afa2 100644 --- gcc/coretypes.h +++ gcc/coretypes.h @@ -52,9 +52,9 @@ typedef const struct bitmap_head *const_bitmap; struct simple_bitmap_def; typedef struct simple_bitmap_def *sbitmap; typedef const struct simple_bitmap_def *const_sbitmap; -struct rtx_def; -typedef struct rtx_def *rtx; -typedef const struct rtx_def *const_rtx; +class rtx_def; +typedef class rtx_def *rtx; +typedef const class rtx_def *const_rtx; /* Subclasses of rtx_def, using indentation to show the class hierarchy, along with the relevant invariant. From bb99da7652edb584a7825632fdccf0db0d7080d4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 12 Feb 2017 12:42:09 +0100 Subject: [PATCH 016/303] @B fixed - on an unsigned value, add cast to signed --- gcc/hwint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/hwint.h b/gcc/hwint.h index 14740ccc939a..cd4a35c98f7b 100644 --- gcc/hwint.h +++ gcc/hwint.h @@ -294,7 +294,7 @@ abs_hwi (HOST_WIDE_INT x) inline unsigned HOST_WIDE_INT absu_hwi (HOST_WIDE_INT x) { - return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(unsigned HOST_WIDE_INT)x; + return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(signed HOST_WIDE_INT)x; } #endif /* ! GCC_HWINT_H */ From e66d5a27e1e5257373172597fe9a699011b011d7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 12 Feb 2017 12:42:45 +0100 Subject: [PATCH 017/303] @N add amiga target --- libgcc/config.host | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgcc/config.host b/libgcc/config.host index 124f2ceaefda..1849a2ec1980 100644 --- libgcc/config.host +++ libgcc/config.host @@ -811,6 +811,9 @@ m32r-*-linux*) m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; +m68k-*-amiga*) + tmake_file="$tmake_file m68k/t-floatlib" + ;; m68k-*-elf* | fido-*-elf) tmake_file="$tmake_file m68k/t-floatlib" ;; From c61b7d29f7f89cbec99115f6dfbb81b5e2967188 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 12 Feb 2017 12:44:25 +0100 Subject: [PATCH 018/303] @B fix specs and linking paths issues --- gcc/config/m68k/amigaos.h | 9 ++++----- gcc/config/m68k/m68kamigaos.h | 41 ++++++++++++++++++++++------------------- gcc/gcc.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index fd89bb34352c..5f3348feb726 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -122,7 +122,6 @@ amiga_named_section (const char *name, unsigned int flags, tree decl); #undef TARGET_ASM_NAMED_SECTION #define TARGET_ASM_NAMED_SECTION amiga_named_section -#if 0 /* Various ABI issues. */ /* This is (almost;-) BSD, so it wants DBX format. */ @@ -183,12 +182,10 @@ amiga_named_section (const char *name, unsigned int flags, tree decl); //#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node) #undef WCHAR_TYPE -#define WCHAR_TYPE "unsigned int" +#define WCHAR_TYPE "unsigned short" /* XXX: section support */ -#if 0 - - +#if 0 /* We define TARGET_ASM_NAMED_SECTION, but we don't support arbitrary sections, including '.gcc_except_table', so we emulate the standard behaviour. */ #undef TARGET_ASM_EXCEPTION_SECTION @@ -222,6 +219,8 @@ do \ } \ while (0) +#if 0 + /* Baserel support. */ /* Given that symbolic_operand(X), return TRUE if no special diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 0650102861e8..6ba2e6736b6a 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -257,10 +257,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{malways-restore-a4:-Derrno=(*ixemul_errno)} " \ "%{mrestore-a4:-Derrno=(*ixemul_errno)}" #define CPP_LIBNIX_SPEC \ - "-isystem %(sdk_root)libnix/include " \ + "-isystem %:sdk_root(libnix/include) " \ "%{!ansi:-Dlibnix} -D__libnix__ -D__libnix" #define CPP_CLIB2_SPEC \ - "-isystem %(sdk_root)clib2/include " \ + "-isystem %:sdk_root(clib2/include) " \ "%{!ansi:-DCLIB2} -D__CLIB2__ -D__CLIB2" /* Define __HAVE_68881__ in preprocessor according to the -m flags. @@ -320,7 +320,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{!resident:%{!fbaserel:%{!resident32:%{!fbaserel32:" \ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}}}" #define STARTFILE_LIBNIX_SPEC \ - "%(sdk_root)lib/libnix/" \ + "%:sdk_root(libnix/lib/libnix/ " \ "%{ramiga-*:" \ "%{ramiga-lib:libinit.o%s}" \ "%{ramiga-libr:libinitr.o%s}" \ @@ -331,10 +331,11 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{fbaserel:nbcrt0.o%s}" \ "%{!fbaserel:" \ "%{fbaserel32:nlbcrt0.o%s}" \ - "%{!fbaserel32:ncrt0.o%s}}}}" + "%{!fbaserel32:ncrt0.o%s}}}}" \ + ")" #define STARTFILE_CLIB2_SPEC \ - "%(sdk_root)clib2/lib/" \ + "%:sdk_root(clib2/lib/ " \ "%{resident32:nr32crt0.o%s}" \ "%{!resident32:" \ "%{fbaserel32:nb32crt0.o%s}" \ @@ -342,7 +343,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{resident:nrcrt0.o%s}" \ "%{!resident:" \ "%{fbaserel:nbcrt0.o%s}" \ - "%{!fbaserel:ncrt0.o%s}}}}" + "%{!fbaserel:ncrt0.o%s}}}}" \ + ")" #undef STARTFILE_SPEC #define STARTFILE_SPEC \ @@ -398,12 +400,11 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{mcrt=clib2:%(lib_clib2)}" #define LIBGCC_IXEMUL_SPEC "" -#define LIBGCC_LIBNIX_SPEC "-lnix " \ +#define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \ "%{mcrt=*:-l%*} " \ "%{!mcrt=*:-lnix20}" #define LIBGCC_CLIB2_SPEC "-lc" -//#define LIBGCC_SPEC "-lgcc " -#define LIBGCC_SPEC " " \ +#define LIBGCC_SPEC "-lgcc " \ "%{noixemul:%(libgcc_libnix)} " \ "%{mcrt=nix*:%(libgcc_libnix)} " \ "%{mcrt=ixemul:%(libgcc_ixemul)} " \ @@ -415,8 +416,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ commandline options. */ #define LINK_IXEMUL_SPEC "" -#define LINK_LIBNIX_SPEC "-L%(sdk_root)libnix/lib -fl libnix" -#define LINK_CLIB2_SPEC "-L%(sdk_root)clib2/lib" +#define LINK_LIBNIX_SPEC "-L%:sdk_root(libnix/lib) -fl libnix" +#define LINK_CLIB2_SPEC "-L%:sdk_root(clib2/lib)" /* If debugging, tell the linker to output amiga-hunk symbols *and* a BSD compatible debug hunk. @@ -428,10 +429,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{mcrt=nix*:%(link_libnix)} " \ "%{mcrt=ixemul:%(link_ixemul)} " \ "%{mcrt=clib2:%(link_clib2)} " \ - "%{fbaserel:%{!resident:-m amiga_bss -fl libb}} " \ - "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb} " \ - "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32}} " \ - "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32} " \ + "%{fbaserel:%{!resident:-m amiga_bss -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \ + "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \ + "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \ + "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \ "%{g:-amiga-debug-hunk} " \ "%{mcpu=68020:-fl libm020} " \ "%{m68020:-fl libm020} " \ @@ -476,7 +477,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{!nostdlib:%{!nodefaultlibs:%G}} " \ "%{T*} }}}}}} " \ +extern const char * amiga_m68k_prefix_func(int, const char **); +#define EXTRA_SPEC_FUNCTIONS \ + { "sdk_root", amiga_m68k_prefix_func }, /* This macro defines names of additional specifications to put in the specs that can be used in various specifications like CC1_SPEC. Its definition @@ -489,10 +493,9 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ Do not define this macro if it does not need to do anything. */ #undef EXTRA_SPECS #define EXTRA_SPECS \ - { "asm_cpu", ASM_CPU_SPEC }, \ - { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \ - { "link_cpu", LINK_CPU_SPEC }, \ - {"sdk_root", TOOLDIR_BASE_PREFIX "m68k-amigaos/"}, \ + {"asm_cpu", ASM_CPU_SPEC }, \ + {"asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \ + {"link_cpu", LINK_CPU_SPEC }, \ {"cpp_ixemul", CPP_IXEMUL_SPEC}, \ {"cpp_libnix", CPP_LIBNIX_SPEC}, \ {"cpp_clib2", CPP_CLIB2_SPEC}, \ diff --git a/gcc/gcc.c b/gcc/gcc.c index 0f042b0f12f7..479a912c7b3e 100644 --- gcc/gcc.c +++ gcc/gcc.c @@ -10075,3 +10075,40 @@ driver_get_configure_time_options (void (*cb) (const char *option, obstack_free (&obstack, NULL); n_switches = 0; } + +#ifdef TARGET_AMIGA +const char * amiga_m68k_prefix_func(int argc, const char ** argv) { + char * p = 0; + if (standard_libexec_prefix) + { + char * glp = concat(standard_libexec_prefix, "",0); + p = strrchr(glp, '/'); + if (p) + { + *p = 0; + p = strrchr(glp, '/'); + if (p) + { + *p = 0; + p = strrchr(glp, '/'); + if (p) + { + p[1] = 0; + p = concat(glp, "m68k-amigaos/", 0); + } + } + } + free(glp); + } + if (!p) + p = concat("../../../../", "", 0); + + for (int i = 0; i < argc; ++i) { + char * q = concat(p, argv[i], 0); + free(p); + p = q; + } +// printf("amiga_m68k_prefix_func='%s'\n", p); + return p; +} +#endif From 476bb08c1155ea1a630fb456301fe273f24caca7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 13 Feb 2017 18:47:13 +0100 Subject: [PATCH 019/303] @B disable builtins which also disables tree-loop-distribute-patterns which causes an infinite recursion since e.g. in memset the pattern is recognized and memset is called... --- gcc/config/m68k/m68kamigaos.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 6ba2e6736b6a..a0ab3f1a91da 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -576,3 +576,5 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP)) #undef FIXED_INCLUDE_DIR #define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../os-include" +// this disables tree_loop_distribute_patterns +#define C_COMMON_OVERRIDE_OPTIONS flag_no_builtin = 1 From c1d1a53baaa94d5560d8e5d9daa749fb8b773b3a Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 16 Feb 2017 12:20:05 +0100 Subject: [PATCH 020/303] @B fix includes for target AMIGA --- libstdc++-v3/include/c_global/cstdio | 2 ++ libstdc++-v3/include/tr1/cstdint | 1 + 2 files changed, 3 insertions(+) diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio index 86d524f96a62..522d065d4dc6 100644 --- libstdc++-v3/include/c_global/cstdio +++ libstdc++-v3/include/c_global/cstdio @@ -149,7 +149,9 @@ namespace std #if _GLIBCXX_USE_C99_STDIO #undef snprintf +#ifndef AMIGA #undef vfscanf +#endif #undef vscanf #undef vsnprintf #undef vsscanf diff --git a/libstdc++-v3/include/tr1/cstdint b/libstdc++-v3/include/tr1/cstdint index 7304d9008413..cdb8b704f0bb 100644 --- libstdc++-v3/include/tr1/cstdint +++ libstdc++-v3/include/tr1/cstdint @@ -31,6 +31,7 @@ #pragma GCC system_header +#include #include // For 8.22.1/1 (see C99, Notes 219, 220, 222) From 8a098e5a7bb1c14c1afa7946dce4416596418e8a Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 16 Feb 2017 13:48:01 +0100 Subject: [PATCH 021/303] @B fix header only for AMIGA --- libstdc++-v3/include/tr1/cstdint | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/tr1/cstdint b/libstdc++-v3/include/tr1/cstdint index cdb8b704f0bb..7d6ab77ce17a 100644 --- libstdc++-v3/include/tr1/cstdint +++ libstdc++-v3/include/tr1/cstdint @@ -30,8 +30,9 @@ #define _GLIBCXX_TR1_CSTDINT 1 #pragma GCC system_header - +#ifdef AMIGA #include +#endif #include // For 8.22.1/1 (see C99, Notes 219, 220, 222) From a3e959953b7386e1576961fb4666f704b2edac7f Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 18 Feb 2017 20:19:06 +0100 Subject: [PATCH 022/303] @V version resports now 6.3.1a instead of 6.3.1 --- gcc/BASE-VER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/BASE-VER b/gcc/BASE-VER index dc0208aba8e4..b557a4031409 100644 --- gcc/BASE-VER +++ gcc/BASE-VER @@ -1 +1 @@ -6.3.1 +6.3.1a From 708b7bc6002cf54e04d7f67e3fdb6627aead7714 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 19 Feb 2017 20:24:20 +0100 Subject: [PATCH 023/303] @B fix __regargs, __stdargs plus register distribution --- gcc/config/m68k/amigaos-protos.h | 4 ++-- gcc/config/m68k/amigaos.c | 19 +++++++++++-------- gcc/config/m68k/amigaos.h | 2 ++ gcc/config/m68k/m68kamigaos.h | 4 ++-- 4 files changed, 17 insertions(+), 12 deletions(-) mode change 100755 => 100644 gcc/config/m68k/amigaos-protos.h diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h old mode 100755 new mode 100644 index 66b553ab568f..97733002f4f9 --- gcc/config/m68k/amigaos-protos.h +++ gcc/config/m68k/amigaos-protos.h @@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */ #undef TARGET_AMIGAOS #define TARGET_AMIGAOS 1 -extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree); +extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree, tree); /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. @@ -32,7 +32,7 @@ extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree); #undef INIT_CUMULATIVE_ARGS #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - (amigaos_init_cumulative_args(&(CUM), (FNTYPE))) + (amigaos_init_cumulative_args(&(CUM), (FNTYPE), (INDIRECT))) extern int amigaos_restore_a4 (void); diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index e2dd5bab75f9..ad4bb9130cd5 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -381,7 +381,7 @@ static CUMULATIVE_ARGS * lastcum; For a library call, FNTYPE is 0. */ void -amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype) +amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) { struct amigaos_args * cum = &mycum; lastcum = cump; @@ -397,11 +397,12 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype) if (fntype) { - if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(fntype))) - cum->num_of_regs = 0; + tree attrs = DECL_ATTRIBUTES(decl); + if (lookup_attribute ("stkparm", attrs)) + cum->num_of_regs = 0; else { - tree ratree = lookup_attribute ("regparm", TYPE_ATTRIBUTES(fntype)); + tree ratree = lookup_attribute ("regparm", attrs); cum->num_of_regs = amigaos_regparm != 0 ? amigaos_regparm : AMIGAOS_DEFAULT_REGPARM; if (ratree) @@ -530,11 +531,11 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) long mask; look_for_reg: mask = 1 << regbegin; - for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1) + for (reg = 0; reg < AMIGAOS_MAX_REGPARM; reg++, mask <<= 1) if (!(cum->regs_already_used & mask)) { int end; - for (end = reg; end < cum->num_of_regs && end < reg + len; + for (end = reg; end < AMIGAOS_MAX_REGPARM && end < reg + len; end++, mask <<= 1) if (cum->regs_already_used & mask) break; @@ -546,8 +547,9 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) } } - if (reg == cum->num_of_regs && altregbegin != -1) + if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) { + DPRINTF(("look for alt reg\n")); regbegin = altregbegin; altregbegin = -1; goto look_for_reg; @@ -556,6 +558,7 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) if (cum->last_arg_reg != -1) { + --cum->num_of_regs; DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg)); return gen_rtx_REG (mode, cum->last_arg_reg); } @@ -771,7 +774,7 @@ bool amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed) { - DPRINTF(("outer: %d, opno: %d", outer_code, opno)); +// DPRINTF(("outer: %d, opno: %d", outer_code, opno)); // debug_rtx(x); bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); *total *= 4; diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 5f3348feb726..71a978e6df97 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -481,6 +481,8 @@ while (0) affects_type_identity } */ #define SUBTARGET_ATTRIBUTES \ { "regparm", 1, 1, true, false, false, amigaos_handle_type_attribute,\ + false }, \ + { "stkparm", 0, 0, true, false, false, amigaos_handle_type_attribute,\ false }, #define GOT_SYMBOL_NAME "" diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index a0ab3f1a91da..539d5f0bf934 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -194,8 +194,8 @@ amiga_declare_object = 0 builtin_define ("__saveds=__attribute__((__saveds__))"); \ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \ builtin_define ("__stackext=__attribute__((__stackext__))"); \ - builtin_define ("__regargs=__attribute__((regparm))"); \ - builtin_define ("__stdargs=__attribute__((stkparm))"); \ + builtin_define ("__regargs=__attribute__((__regparm__))"); \ + builtin_define ("__stdargs=__attribute__((__stkparm__))"); \ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \ builtin_define_std ("amiga"); \ builtin_define_std ("amigaos"); \ From e9ccb451229b09a1fdb64eb125d3ac0c733c5e9e Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 20 Feb 2017 08:32:06 +0100 Subject: [PATCH 024/303] @B do not append (a4) to function references. --- gcc/config/m68k/m68k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index c67194fa292d..bd76c766a735 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -4751,7 +4751,7 @@ print_operand_address (FILE *file, rtx addr) else output_addr_const (file, addr); - if (!RTX_FLAG (addr, frame_related)) + if (!RTX_FLAG (addr, frame_related) && !SYMBOL_REF_FUNCTION_P(addr)) { // debug_rtx(addr); if (flag_mybaserel == 1) From 40f1afb4c03c2bb79e86c5fb8fa2e7daa45d8600 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 20 Feb 2017 08:35:34 +0100 Subject: [PATCH 025/303] @B enable reg-rename in O2+ and fix it. --- gcc/regrename.c | 5 +++-- gcc/toplev.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gcc/regrename.c b/gcc/regrename.c index 9643f328ea3e..9816d3eaf5d2 100644 --- gcc/regrename.c +++ gcc/regrename.c @@ -406,8 +406,9 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, /* In the first pass, we force the renaming of registers that don't belong to PREFERRED_CLASS to registers that do, even - though the latters were used not very long ago. */ - if ((pass == 0 + though the latters were used not very long ago. + Also use a register if no best_new_reg was found till now */ + if (((pass == 0 || !has_preferred_class) && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], best_new_reg)) || tick[best_new_reg] > tick[new_reg]) diff --git a/gcc/toplev.c b/gcc/toplev.c index 8979d2634260..96d17ee1cccc 100644 --- gcc/toplev.c +++ gcc/toplev.c @@ -1299,7 +1299,7 @@ process_options (void) flag_web = flag_unroll_loops || flag_peel_loops; if (flag_rename_registers == AUTODETECT_VALUE) - flag_rename_registers = flag_unroll_loops || flag_peel_loops; + flag_rename_registers = flag_unroll_loops || flag_peel_loops || optimize >= 2; if (flag_non_call_exceptions) flag_asynchronous_unwind_tables = 1; From b980bd29d8cf05a2c6d6c947547b3f1e1c4cff23 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 20 Feb 2017 10:52:45 +0100 Subject: [PATCH 026/303] @B fix npe in amigaos_init_cumulative_args --- gcc/config/m68k/amigaos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index ad4bb9130cd5..c675bc8e01ed 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -395,7 +395,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) cum->last_arg_reg = -1; cum->regs_already_used = 0; - if (fntype) + if (decl) { tree attrs = DECL_ATTRIBUTES(decl); if (lookup_attribute ("stkparm", attrs)) From 215f15335dca293e65f47fde15a3d6486c551629 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Feb 2017 12:46:18 +0100 Subject: [PATCH 027/303] @B -mregparm conforms now to the spec. --- gcc/config/m68k/amigaos.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index c675bc8e01ed..916140bdc628 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -386,7 +386,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) struct amigaos_args * cum = &mycum; lastcum = cump; cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; - DPRINTF(("amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); + DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. @@ -451,6 +451,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) else /* Call to compiler-support function. */ cum->formal_type = 0; + DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); } /* Update the data in CUM to advance over an argument. */ @@ -531,11 +532,11 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) long mask; look_for_reg: mask = 1 << regbegin; - for (reg = 0; reg < AMIGAOS_MAX_REGPARM; reg++, mask <<= 1) + for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1) if (!(cum->regs_already_used & mask)) { int end; - for (end = reg; end < AMIGAOS_MAX_REGPARM && end < reg + len; + for (end = reg; end < cum->num_of_regs && end < reg + len; end++, mask <<= 1) if (cum->regs_already_used & mask) break; @@ -547,18 +548,17 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) } } - if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) - { - DPRINTF(("look for alt reg\n")); - regbegin = altregbegin; - altregbegin = -1; - goto look_for_reg; - } +// if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) +// { +// DPRINTF(("look for alt reg\n")); +// regbegin = altregbegin; +// altregbegin = -1; +// goto look_for_reg; +// } } if (cum->last_arg_reg != -1) { - --cum->num_of_regs; DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg)); return gen_rtx_REG (mode, cum->last_arg_reg); } From 419b54e138b5322b468189fbf9e234f6315b0914 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Feb 2017 12:47:40 +0100 Subject: [PATCH 028/303] @B if -fbaserel32 -m68020 (or better) must be present too --- gcc/config/m68k/amigaos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 71a978e6df97..afc2c6563143 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -470,7 +470,7 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*); #define SUBTARGET_OVERRIDE_OPTIONS \ do \ { \ - if (!TARGET_68020 && flag_pic==2) \ + if (!TARGET_68020 && flag_mybaserel==2) \ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \ From f76ce97a5f8b9542814e5700e9d728ede215749d Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Feb 2017 12:48:23 +0100 Subject: [PATCH 029/303] @I -msmall-code sets now flag_smallcode --- gcc/config/m68k/amigaos.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 212ab8e6efda..1faa3f2eeb26 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -8,7 +8,7 @@ Target RejectNegative Do not use ixemul.library - use libnix instead to link msmall-code -Target RejectNegative +Target RejectNegative Var(flag_smallcode,1) small code model fbaserel From d08bd9d2a479285104f394f70be45e5f77dfa419 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Feb 2017 12:50:51 +0100 Subject: [PATCH 030/303] @B fix baserel(32): use a4 only if common or bss is referenced @N support -msmall-code --- gcc/config/m68k/m68k.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index bd76c766a735..b6ef99024ea6 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -4751,14 +4751,38 @@ print_operand_address (FILE *file, rtx addr) else output_addr_const (file, addr); - if (!RTX_FLAG (addr, frame_related) && !SYMBOL_REF_FUNCTION_P(addr)) +#ifdef TARGET_AMIGA + if (SYMBOL_REF_FUNCTION_P(addr)) { -// debug_rtx(addr); - if (flag_mybaserel == 1) - asm_fprintf (file, ".w(a4)"); - else if (flag_mybaserel == 2) - asm_fprintf (file, "(a4)"); + if (flag_smallcode) + asm_fprintf(file, ":w(pc)"); } + else if (flag_mybaserel) + { + /* search the decl. */ + tree decl = SYMBOL_REF_DECL (addr); + if (!decl) + { + rtx x = XEXP(addr, 0); + if (CONSTANT_POOL_ADDRESS_P(x)) + decl = SYMBOL_REF_DECL (x); + if (!decl) + { + x = XEXP(x, 0); + decl = SYMBOL_REF_DECL (x); + } + } + + /* Qualifies for a4 if common or bss. Do not ref to .text! */ + if (decl && (DECL_COMMON (decl) || bss_initializer_p (decl))) + { + if (flag_mybaserel == 1) + asm_fprintf (file, ":W(a4)"); + else if (flag_mybaserel == 2) + asm_fprintf (file, ":L(a4)"); + } + } +#endif } } else From c72e9ebfc07a0b31d523b9d7428544427fe551b7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Feb 2017 20:15:17 +0100 Subject: [PATCH 031/303] @B undo a too optimistic change ;) --- gcc/regrename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/regrename.c b/gcc/regrename.c index 9816d3eaf5d2..df4c320700c5 100644 --- gcc/regrename.c +++ gcc/regrename.c @@ -408,7 +408,7 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, don't belong to PREFERRED_CLASS to registers that do, even though the latters were used not very long ago. Also use a register if no best_new_reg was found till now */ - if (((pass == 0 || !has_preferred_class) + if (((pass == 0) && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], best_new_reg)) || tick[best_new_reg] > tick[new_reg]) From 181421087bf57fab0f047c47861b5c2a1e745d96 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Mar 2017 21:38:30 +0100 Subject: [PATCH 032/303] @R add better -fbaserel(32) support for TARGET_AMIGA --- gcc/BASE-VER | 2 +- gcc/config/m68k/amigaos.c | 51 +++++++++++++---- gcc/config/m68k/amigaos.h | 21 +++---- gcc/config/m68k/amigaos.opt | 4 +- gcc/config/m68k/m68k.c | 130 ++++++++++++++++++++++++++++-------------- gcc/config/m68k/m68k.md | 6 +- gcc/config/m68k/m68kamigaos.h | 23 ++++++++ gcc/config/m68k/predicates.md | 4 ++ 8 files changed, 170 insertions(+), 71 deletions(-) diff --git a/gcc/BASE-VER b/gcc/BASE-VER index b557a4031409..6352d5267189 100644 --- gcc/BASE-VER +++ gcc/BASE-VER @@ -1 +1 @@ -6.3.1a +6.3.1b diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 916140bdc628..81d08245b580 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -548,13 +548,13 @@ _m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) } } -// if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) -// { -// DPRINTF(("look for alt reg\n")); -// regbegin = altregbegin; -// altregbegin = -1; -// goto look_for_reg; -// } + if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) + { + DPRINTF(("look for alt reg\n")); + regbegin = altregbegin; + altregbegin = -1; + goto look_for_reg; + } } if (cum->last_arg_reg != -1) @@ -775,9 +775,10 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed) { // DPRINTF(("outer: %d, opno: %d", outer_code, opno)); -// debug_rtx(x); bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); - *total *= 4; +// *total *= 4; +// fprintf(stderr, "costs: %d, mode=%d, outer=%d, opno=%d, speed=%d, ok=%d\n", *total * 4, mode, outer_code, opno, speed, r); +// debug_rtx(x); return r; } @@ -789,7 +790,37 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U { if (0 == strncmp(".text", name, 5)) name = ".text"; -// fprintf (asm_out_file, "\t.section\t%s\n", name); fprintf (asm_out_file, "\t%s\n", name); } +/* Baserel support. */ + +/** + * Does x reference the pic_reg and is const or plus? + */ +int amiga_is_const_pic_ref(const_rtx x) +{ + const_rtx y = x; + if (flag_pic < 3) + return false; + while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS) + y = XEXP(y, 0); + return (x != y && REG_P(y) && REGNO(y) == PIC_REG); +} + + +/* Does operand (which is a symbolic_operand) live in text space? If + so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. + + This function is used in base relative code generation. */ + +int +read_only_operand (rtx operand) +{ + if (GET_CODE (operand) == CONST) + operand = XEXP (XEXP (operand, 0), 0); + if (GET_CODE (operand) == SYMBOL_REF) + return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + return 1; +} + diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index afc2c6563143..9820f0ed1219 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -221,18 +221,6 @@ while (0) #if 0 -/* Baserel support. */ - -/* Given that symbolic_operand(X), return TRUE if no special - base relative relocation is necessary */ - -#define LEGITIMATE_BASEREL_OPERAND_P(X) \ - (flag_pic >= 3 && read_only_operand (X)) - -#undef LEGITIMATE_PIC_OPERAND_P -#define LEGITIMATE_PIC_OPERAND_P(X) \ - (! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X)) - /* Define this macro if references to a symbol must be treated differently depending on something about the variable or function named by the symbol (such as what section it is in). @@ -492,3 +480,12 @@ while (0) bool amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool); +/* SBF: macro to test for const via pic_reg. */ +#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \ + (GET_CODE(x) == CONST \ + && GET_CODE(XEXP(x, 0)) == PLUS \ + && REG_P(XEXP(XEXP(x, 0), 0)) \ + && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \ + && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \ + && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ + ) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 1faa3f2eeb26..4d9a42052355 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -12,11 +12,11 @@ Target RejectNegative Var(flag_smallcode,1) small code model fbaserel -Target Common Report Var(flag_mybaserel,1) +Target Report Var(flag_pic,3) data is adressed relativ to a4 fbaserel32 -Target Common Report Var(flag_mybaserel,2) +Target Report Var(flag_pic,4) data is adressed relativ to a4 with 32 bit offsets resident diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index b6ef99024ea6..64dcbf6969ee 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -591,7 +591,8 @@ m68k_option_override (void) if (TARGET_PCREL && flag_pic == 0) flag_pic = 1; - if (!flag_pic) + /* SBF: use normal jumps/calls with baserel(32) modes. */ + if (!flag_pic || flag_pic > 2) { m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_JSR; @@ -888,8 +889,9 @@ m68k_save_reg (unsigned int regno, bool interrupt_handler) { if (crtl->saves_all_registers) return true; + /* SBF: do not save the PIC_REG with baserel(32) modes. */ if (crtl->uses_pic_offset_table) - return true; + return flag_pic < 3; /* Reload may introduce constant pool references into a function that thitherto didn't need a PIC register. Note that the test above will not catch that case because we will only set @@ -1149,8 +1151,9 @@ m68k_expand_prologue (void) current_frame.reg_mask, true, true)); } + /* SBF: do not load the PIC_REG with baserel(32) */ if (!TARGET_SEP_DATA - && crtl->uses_pic_offset_table) + && crtl->uses_pic_offset_table && flag_pic < 3) emit_insn (gen_load_got (pic_offset_table_rtx)); } @@ -2135,6 +2138,12 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p) { struct m68k_address address; +#ifdef TARGET_AMIGA + /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */ + if (amiga_is_const_pic_ref(x)) + return true; +#endif + return m68k_decompose_address (mode, x, strict_p, &address); } @@ -2468,9 +2477,33 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) { gcc_assert (reg); - pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg); - pic_ref = m68k_move_to_reg (pic_ref, orig, reg); -// debug_rtx(pic_ref); + if (flag_pic < 3) + { + pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg); + pic_ref = m68k_move_to_reg (pic_ref, orig, reg); + } + #ifdef TARGET_AMIGA + else + { + tree decl = SYMBOL_REF_DECL (orig); + + /* SBF: Does the symbol use common or bss and qualifies for pic_reg? + * Do not ref to .text via pic_reg! + */ + if (!SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl))) + { + /* SBF: unfortunately using the wrapped symbol without MEM does not work. + * The pic_ref reference gets decomposed and leads to no working code. + */ + pic_ref = m68k_wrap_symbol (pic_ref, RELOC_GOT, m68k_get_gp (), reg); + + /* SBF: adding const avoids decomposing. */ + pic_ref = gen_rtx_CONST (Pmode, pic_ref); + } + else + pic_ref = gen_rtx_CONST (Pmode, pic_ref); + } +#endif } else if (GET_CODE (orig) == CONST) { @@ -2489,7 +2522,8 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, base == reg ? 0 : reg); - if (GET_CODE (orig) == CONST_INT) + /* SBF: use normal plus and rely on optimizer with baserel(32). */ + if (flag_pic < 3 && GET_CODE (orig) == CONST_INT) pic_ref = plus_constant (Pmode, base, INTVAL (orig)); else pic_ref = gen_rtx_PLUS (Pmode, base, orig); @@ -4453,7 +4487,6 @@ floating_exact_log2 (rtx x) void print_operand (FILE *file, rtx op, int letter) { -// printf("letter: %c\n", letter); if (letter == '.') { if (MOTOROLA) @@ -4486,7 +4519,9 @@ print_operand (FILE *file, rtx op, int letter) else if (letter == 'p') { output_addr_const (file, op); - if (!(GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op))) + /* SBF: do not add @PLTPC with baserel(32). */ + if (flag_pic < 3 + && !(GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op))) fprintf (file, "@PLTPC"); } else if (GET_CODE (op) == REG) @@ -4505,10 +4540,12 @@ print_operand (FILE *file, rtx op, int letter) && CONSTANT_ADDRESS_P (XEXP (op, 0)) && !(GET_CODE (XEXP (op, 0)) == CONST_INT && INTVAL (XEXP (op, 0)) < 0x8000 - && INTVAL (XEXP (op, 0)) >= -0x8000)) + && INTVAL (XEXP (op, 0)) >= -0x8000) #ifdef TARGET_AMIGA - if (!flag_mybaserel) +/* SBF: Do not append some 'l' with baserel(32). */ + && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(op, 0)) #endif + ) fprintf (file, MOTOROLA ? ".l" : ":l"); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) @@ -4554,9 +4591,18 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc) switch (reloc) { case RELOC_GOT: -// if (TARGET_AMIGA) -// return ""; -// else + /* SBF: add the proper extension for baserel relocs with baserel(32). */ + if (TARGET_AMIGA) + { + if (flag_pic == 1) + return ".w"; + else if (flag_pic == 3) + return ":W"; + else if (flag_pic == 4) + return ":L"; + else + return ""; + } if (MOTOROLA) { if (flag_pic == 1 && TARGET_68020) @@ -4707,6 +4753,22 @@ print_operand_address (FILE *file, rtx addr) { struct m68k_address address; +#ifdef TARGET_AMIGA + /* + * SBF: remove the const wrapper. + */ + if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(addr)) + { + print_operand_address(file, XEXP(addr, 0)); + return; + } + if (symbolic_operand(addr, VOIDmode)) + { + memset (&address, 0, sizeof (address)); + address.offset = addr; + } + else +#endif if (!m68k_decompose_address (QImode, addr, true, &address)) gcc_unreachable (); @@ -4757,31 +4819,6 @@ print_operand_address (FILE *file, rtx addr) if (flag_smallcode) asm_fprintf(file, ":w(pc)"); } - else if (flag_mybaserel) - { - /* search the decl. */ - tree decl = SYMBOL_REF_DECL (addr); - if (!decl) - { - rtx x = XEXP(addr, 0); - if (CONSTANT_POOL_ADDRESS_P(x)) - decl = SYMBOL_REF_DECL (x); - if (!decl) - { - x = XEXP(x, 0); - decl = SYMBOL_REF_DECL (x); - } - } - - /* Qualifies for a4 if common or bss. Do not ref to .text! */ - if (decl && (DECL_COMMON (decl) || bss_initializer_p (decl))) - { - if (flag_mybaserel == 1) - asm_fprintf (file, ":W(a4)"); - else if (flag_mybaserel == 2) - asm_fprintf (file, ":L(a4)"); - } - } #endif } } @@ -5224,7 +5261,9 @@ m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED, /* Value is true if hard register REGNO can hold a value of machine-mode MODE. On the 68000, we let the cpu registers can hold any mode, but - restrict the 68881 registers to floating-point modes. */ + restrict the 68881 registers to floating-point modes. + SBF: Disallow the frame pointer register, if the frame pointer is used. + */ bool m68k_regno_mode_ok (int regno, machine_mode mode) @@ -5233,12 +5272,12 @@ m68k_regno_mode_ok (int regno, machine_mode mode) { /* Data Registers, can hold aggregate if fits in. */ if (regno + GET_MODE_SIZE (mode) / 4 <= 8) - return true; + return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM; } else if (ADDRESS_REGNO_P (regno)) { if (regno + GET_MODE_SIZE (mode) / 4 <= 16) - return true; + return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM; } else if (FP_REGNO_P (regno)) { @@ -5259,6 +5298,13 @@ m68k_secondary_reload_class (enum reg_class rclass, machine_mode mode, rtx x) { int regno; +#ifdef TARGET_AMIGA + /* SBF: check for baserel's const pic_ref + * and return ADDR_REGS or NO_REGS + */ + if (!MEM_P(x) && amiga_is_const_pic_ref(x)) + return rclass == ADDR_REGS ? NO_REGS : ADDR_REGS; +#endif regno = true_regnum (x); diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index f5b63f43c372..24332476b91b 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -128,13 +128,11 @@ (UNSPECV_TAS_2 4) ]) -;; Registers by name. +;; Registers by name. SBF: Do not define PIC_REG / A6_REG here! (define_constants [(D0_REG 0) (A0_REG 8) (A1_REG 9) - (PIC_REG 13) - (A6_REG 14) (SP_REG 15) (FP0_REG 16) ]) @@ -502,7 +500,7 @@ [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>") (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))] - "!TARGET_COLDFIRE" + "!TARGET_COLDFIRE && (flag_pic < 3 || GET_CODE(operands[1]) != CONST || GET_CODE(XEXP(operands[1], 0)) != PLUS || !REG_P(XEXP(XEXP(operands[1], 0), 0)) || REGNO(XEXP(XEXP(operands[1], 0), 0)) != PIC_REG)" { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.l %1,%0"; diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 539d5f0bf934..74403a50bb67 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -578,3 +578,26 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP)) // this disables tree_loop_distribute_patterns #define C_COMMON_OVERRIDE_OPTIONS flag_no_builtin = 1 +/* Baserel support. */ + +extern int amiga_is_const_pic_ref(const_rtx x); + +#undef CONSTANT_ADDRESS_P +#define CONSTANT_ADDRESS_P(X) \ +((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ + || GET_CODE (X) == HIGH \ + ) && !amiga_is_const_pic_ref(X)) + + +/* Given that symbolic_operand(X), return TRUE if no special + base relative relocation is necessary */ + +#define LEGITIMATE_BASEREL_OPERAND_P(X) \ + (flag_pic >= 3 && read_only_operand (X)) + +#undef LEGITIMATE_PIC_OPERAND_P +#define LEGITIMATE_PIC_OPERAND_P(X) ( \ + ! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X)) + +// (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) || diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md index 186436c42b77..9533e65ceaab 100644 --- gcc/config/m68k/predicates.md +++ gcc/config/m68k/predicates.md @@ -30,6 +30,10 @@ || GET_CODE (XEXP (op, 0)) == LABEL_REF || GET_CODE (XEXP (op, 0)) == CONST)) return 1; +#ifdef TARGET_AMIGA + if (flag_pic >= 3 && amiga_is_const_pic_ref(op)) + return 0; +#endif return general_operand (op, mode); }) From e74ef22307cef4b728ea06a9bb78f24d3c7879d6 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 20 Mar 2017 22:47:47 +0100 Subject: [PATCH 033/303] @R improved register renamingRegister renaming now updates the register ref count. Also the stack variable creation is scheduled later, to omitt push/pop of unused variables.The regs d0/a0 are preferred and rarely renamed. --- gcc/calls.c | 2 +- gcc/config/m68k/amigaos.c | 9 +++++ gcc/config/m68k/amigaos.h | 5 +++ gcc/config/m68k/m68k.c | 12 ++++--- gcc/config/m68k/m68k.h | 10 +++--- gcc/df-scan.c | 7 ++++ gcc/doc/tm.texi | 4 +++ gcc/doc/tm.texi.in | 2 ++ gcc/expr.c | 2 +- gcc/passes.def | 6 ++-- gcc/regrename.c | 84 +++++++++++++++++++++++++++-------------------- gcc/target.def | 19 +++++++++++ gcc/targhooks.c | 7 ++++ gcc/targhooks.h | 1 + 14 files changed, 120 insertions(+), 50 deletions(-) diff --git a/gcc/calls.c b/gcc/calls.c index 730d82e65cf3..c78059fb5199 100644 --- gcc/calls.c +++ gcc/calls.c @@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" -#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "gimple.h" #include "predict.h" +#include "tm_p.h" #include "stringpool.h" #include "expmed.h" #include "optabs.h" diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 81d08245b580..88205e25476e 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -824,3 +824,12 @@ read_only_operand (rtx operand) return 1; } +reg_class_t +amiga_preferred_rename_class2(reg_class_t rclass ATTRIBUTE_UNUSED, int regno ) +{ + if (regno == 0) + return D0_REGS; + if (regno == 8) + return A0_REGS; + return regno_reg_class[regno]; +} diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 9820f0ed1219..7259611edc9e 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -489,3 +489,8 @@ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool); && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \ && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ ) + +#undef TARGET_PREFERRED_RENAME_CLASS2 +#define TARGET_PREFERRED_RENAME_CLASS2 amiga_preferred_rename_class2 +reg_class_t +amiga_preferred_rename_class2(reg_class_t, int); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 64dcbf6969ee..d60371a92bc6 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -801,9 +801,11 @@ m68k_compute_frame_layout (void) /* Only compute the frame once per function. Don't cache information until reload has been completed. */ - if (current_frame.funcdef_no == current_function_funcdef_no - && reload_completed) - return; + /* SBF: No. Register renaming may free some variables, + * => compute it again and again... */ +// if (current_frame.funcdef_no == current_function_funcdef_no +// && reload_completed) +// return; current_frame.size = (get_frame_size () + 3) & -4; @@ -5272,12 +5274,12 @@ m68k_regno_mode_ok (int regno, machine_mode mode) { /* Data Registers, can hold aggregate if fits in. */ if (regno + GET_MODE_SIZE (mode) / 4 <= 8) - return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM; + return true; } else if (ADDRESS_REGNO_P (regno)) { if (regno + GET_MODE_SIZE (mode) / 4 <= 16) - return !flag_omit_frame_pointer || regno != FRAME_POINTER_REGNUM; + return !frame_pointer_needed || regno != FRAME_POINTER_REGNUM; } else if (FP_REGNO_P (regno)) { diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 74d5aa042059..5142adf24e4d 100644 --- gcc/config/m68k/m68k.h +++ gcc/config/m68k/m68k.h @@ -440,8 +440,8 @@ along with GCC; see the file COPYING3. If not see /* The m68k has three kinds of registers, so eight classes would be a complete set. One of them is not needed. */ enum reg_class { - NO_REGS, DATA_REGS, - ADDR_REGS, FP_REGS, + NO_REGS, DATA_REGS, D0_REGS, + ADDR_REGS, A0_REGS, FP_REGS, GENERAL_REGS, DATA_OR_FP_REGS, ADDR_OR_FP_REGS, ALL_REGS, LIM_REG_CLASSES }; @@ -449,8 +449,8 @@ enum reg_class { #define N_REG_CLASSES (int) LIM_REG_CLASSES #define REG_CLASS_NAMES \ - { "NO_REGS", "DATA_REGS", \ - "ADDR_REGS", "FP_REGS", \ + { "NO_REGS", "DATA_REGS", "D0_REGS" \ + "ADDR_REGS", "A0_REGS", "FP_REGS", \ "GENERAL_REGS", "DATA_OR_FP_REGS", \ "ADDR_OR_FP_REGS", "ALL_REGS" } @@ -458,7 +458,9 @@ enum reg_class { { \ {0x00000000}, /* NO_REGS */ \ {0x000000ff}, /* DATA_REGS */ \ + {0x00000001}, /* D0_REGS */ \ {0x0100ff00}, /* ADDR_REGS */ \ + {0x00000100}, /* A0_REGS */ \ {0x00ff0000}, /* FP_REGS */ \ {0x0100ffff}, /* GENERAL_REGS */ \ {0x00ff00ff}, /* DATA_OR_FP_REGS */ \ diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 98de84405428..b0ef0813d07d 100644 --- gcc/df-scan.c +++ gcc/df-scan.c @@ -1807,6 +1807,13 @@ df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df, df_ref *ref_ptr; struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref); + if (DF_REF_FLAGS_IS_SET(the_ref, DF_HARD_REG_LIVE)) + { + if (DF_REF_REGNO(the_ref) < FIRST_PSEUDO_REGISTER) + --df->hard_regs_live_count[DF_REF_REGNO(the_ref)]; + ++df->hard_regs_live_count[new_regno]; + } + DF_REF_REGNO (the_ref) = new_regno; DF_REF_REG (the_ref) = regno_reg_rtx[new_regno]; diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 745910f9a331..6604514427fa 100644 --- gcc/doc/tm.texi +++ gcc/doc/tm.texi @@ -2489,6 +2489,10 @@ only if neither labeling works. A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class}, code size can be reduced. @end deftypefn +@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RENAME_CLASS2 (reg_class_t @var{rclass}, int @var{regno}) +A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class2} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class2}, code size can be reduced. +@end deftypefn + @deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass}) A target hook that places additional restrictions on the register class to use when it is necessary to copy value @var{x} into a register in class diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f31c763991c5..e4da2a94249b 100644 --- gcc/doc/tm.texi.in +++ gcc/doc/tm.texi.in @@ -2281,6 +2281,8 @@ only if neither labeling works. @hook TARGET_PREFERRED_RENAME_CLASS +@hook TARGET_PREFERRED_RENAME_CLASS2 + @hook TARGET_PREFERRED_RELOAD_CLASS @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class}) diff --git a/gcc/expr.c b/gcc/expr.c index 01fe6437da12..6260f5ed7ed2 100644 --- gcc/expr.c +++ gcc/expr.c @@ -21,12 +21,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" -#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "gimple.h" #include "predict.h" +#include "tm_p.h" #include "ssa.h" #include "expmed.h" #include "optabs.h" diff --git a/gcc/passes.def b/gcc/passes.def index 7aed14445429..ec796082ae7f 100644 --- gcc/passes.def +++ gcc/passes.def @@ -447,9 +447,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_ree); NEXT_PASS (pass_compare_elim_after_reload); NEXT_PASS (pass_branch_target_load_optimize1); - NEXT_PASS (pass_thread_prologue_and_epilogue); - NEXT_PASS (pass_rtl_dse2); - NEXT_PASS (pass_stack_adjustments); NEXT_PASS (pass_jump2); NEXT_PASS (pass_duplicate_computed_gotos); NEXT_PASS (pass_sched_fusion); @@ -457,6 +454,9 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_if_after_reload); NEXT_PASS (pass_regrename); NEXT_PASS (pass_cprop_hardreg); + NEXT_PASS (pass_thread_prologue_and_epilogue); + NEXT_PASS (pass_rtl_dse2); + NEXT_PASS (pass_stack_adjustments); NEXT_PASS (pass_fast_rtl_dce); NEXT_PASS (pass_reorder_blocks); NEXT_PASS (pass_branch_target_load_optimize2); diff --git a/gcc/regrename.c b/gcc/regrename.c index df4c320700c5..ca7e24774afd 100644 --- gcc/regrename.c +++ gcc/regrename.c @@ -370,32 +370,31 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, /* Compute preferred rename class of super union of all the classes in the chain. */ - preferred_class - = (enum reg_class) targetm.preferred_rename_class (super_class); + preferred_class = (enum reg_class) targetm.preferred_rename_class2 ( + super_class, old_reg); /* Pick and check the register from the tied chain iff the tied chain - is not renamed. */ + is not renamed. */ if (this_head->tied_chain && !this_head->tied_chain->renamed - && check_new_reg_p (old_reg, this_head->tied_chain->regno, - this_head, *unavailable)) + && check_new_reg_p (old_reg, this_head->tied_chain->regno, this_head, + *unavailable)) return this_head->tied_chain->regno; /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass - over registers that belong to PREFERRED_CLASS and try to find the - best register within the class. If that failed, we iterate in - the second pass over registers that don't belong to the class. - If PREFERRED_CLASS is NO_REGS, we iterate over all registers in - ascending order without any preference. */ + over registers that belong to PREFERRED_CLASS and try to find the + best register within the class. If that failed, we iterate in + the second pass over registers that don't belong to the class. + If PREFERRED_CLASS is NO_REGS, we iterate over all registers in + ascending order without any preference. */ has_preferred_class = (preferred_class != NO_REGS); - for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++) { int new_reg; for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++) { if (has_preferred_class - && (pass == 0) - != TEST_HARD_REG_BIT (reg_class_contents[preferred_class], - new_reg)) + && 0 + == TEST_HARD_REG_BIT(reg_class_contents[preferred_class], + new_reg)) continue; if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable)) @@ -405,17 +404,13 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, return new_reg; /* In the first pass, we force the renaming of registers that - don't belong to PREFERRED_CLASS to registers that do, even - though the latters were used not very long ago. - Also use a register if no best_new_reg was found till now */ - if (((pass == 0) - && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], - best_new_reg)) - || tick[best_new_reg] > tick[new_reg]) + don't belong to PREFERRED_CLASS to registers that do, even + though the latters were used not very long ago. + Also use a register if no best_new_reg was found till now */ + if ((tick[best_new_reg] > tick[new_reg] + || (old_reg == best_new_reg && new_reg < old_reg))) best_new_reg = new_reg; } - if (pass == 0 && best_new_reg != old_reg) - break; } return best_new_reg; } @@ -955,7 +950,7 @@ regrename_analyze (bitmap bb_mask) numbering in its subpatterns. */ bool -regrename_do_replace (struct du_head *head, int reg) +regrename_do_replace (struct du_head *head, int regno) { struct du_chain *chain; unsigned int base_regno = head->regno; @@ -963,19 +958,20 @@ regrename_do_replace (struct du_head *head, int reg) for (chain = head->first; chain; chain = chain->next_use) { - unsigned int regno = ORIGINAL_REGNO (*chain->loc); - struct reg_attrs *attr = REG_ATTRS (*chain->loc); - int reg_ptr = REG_POINTER (*chain->loc); + unsigned int orig_regno = ORIGINAL_REGNO(*chain->loc); + struct reg_attrs *attr = REG_ATTRS(*chain->loc); + int reg_ptr = REG_POINTER(*chain->loc); if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno) - validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC (chain->insn)), - gen_rtx_UNKNOWN_VAR_LOC (), true); + validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC(chain->insn)), + gen_rtx_UNKNOWN_VAR_LOC (), + true); else { - validate_change (chain->insn, chain->loc, - gen_raw_REG (GET_MODE (*chain->loc), reg), true); - if (regno >= FIRST_PSEUDO_REGISTER) - ORIGINAL_REGNO (*chain->loc) = regno; + validate_change (chain->insn, chain->loc, + gen_raw_REG (GET_MODE(*chain->loc), regno), true); + if (orig_regno >= FIRST_PSEUDO_REGISTER) + ORIGINAL_REGNO (*chain->loc) = orig_regno; REG_ATTRS (*chain->loc) = attr; REG_POINTER (*chain->loc) = reg_ptr; } @@ -984,10 +980,26 @@ regrename_do_replace (struct du_head *head, int reg) if (!apply_change_group ()) return false; - mode = GET_MODE (*head->first->loc); + mode = GET_MODE(*head->first->loc); head->renamed = 1; - head->regno = reg; - head->nregs = hard_regno_nregs[reg][mode]; + head->regno = regno; + head->nregs = hard_regno_nregs[regno][mode]; + + /* SBF: also update the current df info, move from base_regno -> regno. */ + for (chain = head->first; chain; chain = chain->next_use) + { + /* undo regno patch - will be patched again */ + if (REGNO (*chain->loc) == regno) + SET_REGNO(*chain->loc, base_regno); + df_ref_change_reg_with_loc (*chain->loc, regno); + + SET_REGNO(*chain->loc, regno); + } + + /* Mark the old regno as no longer used. */ + if (!df->hard_regs_live_count[base_regno]) + df_set_regs_ever_live (base_regno, false); + return true; } diff --git a/gcc/target.def b/gcc/target.def index 20f2b32da1e9..d0208812d83b 100644 --- gcc/target.def +++ gcc/target.def @@ -5170,6 +5170,25 @@ DEFHOOK reg_class_t, (reg_class_t rclass), default_preferred_rename_class) +/*A target hook that places additional preference on the register + class + */ +DEFHOOK +(preferred_rename_class2, + "A target hook that places additional preference on the register\ + class to use when it is necessary to rename a register in class\ + @var{rclass} to another class, or perhaps @var{NO_REGS}, if no\ + preferred register class is found or hook @code{preferred_rename_class2}\ + is not implemented.\ + Sometimes returning a more restrictive class makes better code. For\ + example, on ARM, thumb-2 instructions using @code{LO_REGS} may be\ + smaller than instructions using @code{GENERIC_REGS}. By returning\ + @code{LO_REGS} from @code{preferred_rename_class2}, code size can\ + be reduced.", + reg_class_t, (reg_class_t rclass, int regno), + default_preferred_rename_class2) + + /* This target hook allows the backend to avoid unsafe substitution during register allocation. */ DEFHOOK diff --git a/gcc/targhooks.c b/gcc/targhooks.c index a34227705d2b..e106af7b261d 100644 --- gcc/targhooks.c +++ gcc/targhooks.c @@ -1542,6 +1542,13 @@ default_preferred_rename_class (reg_class_t rclass ATTRIBUTE_UNUSED) return NO_REGS; } +/* The default implementation of TARGET_PREFERRED_RENAME_CLASS2. */ +reg_class_t +default_preferred_rename_class2 (reg_class_t rclass, int regno ATTRIBUTE_UNUSED) +{ + return targetm.preferred_rename_class(rclass); +} + /* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P. */ bool diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 7687c39b53b5..0a21ef982a65 100644 --- gcc/targhooks.h +++ gcc/targhooks.h @@ -204,6 +204,7 @@ extern bool default_profile_before_prologue (void); extern reg_class_t default_preferred_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_rename_class (reg_class_t rclass); +extern reg_class_t default_preferred_rename_class2 (reg_class_t rclass, int regno); extern bool default_class_likely_spilled_p (reg_class_t); extern unsigned char default_class_max_nregs (reg_class_t, machine_mode); From 6b9057baef40c5661b35c995f764401a82fcf9b7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 20 Mar 2017 23:11:56 +0100 Subject: [PATCH 034/303] @B fix include order --- gcc/function.c | 2 +- gcc/var-tracking.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/function.c b/gcc/function.c index e903b1bcdf65..c614f9b9c000 100644 --- gcc/function.c +++ gcc/function.c @@ -35,11 +35,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" -#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" #include "gimple-expr.h" +#include "tm_p.h" #include "cfghooks.h" #include "df.h" #include "stringpool.h" diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 149c0c123804..ab9c0117b078 100644 --- gcc/var-tracking.c +++ gcc/var-tracking.c @@ -89,10 +89,10 @@ #include "system.h" #include "coretypes.h" #include "backend.h" -#include "tm_p.h" #include "target.h" #include "rtl.h" #include "tree.h" +#include "tm_p.h" #include "cfghooks.h" #include "alloc-pool.h" #include "tree-pass.h" From 1176f20fb5eb00f735a1c1ad2bb9d005fdac44aa Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 21 Mar 2017 00:15:07 +0100 Subject: [PATCH 035/303] @B fix pssible NPE --- gcc/regrename.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/gcc/regrename.c b/gcc/regrename.c index ca7e24774afd..4a9b4c2735a1 100644 --- gcc/regrename.c +++ gcc/regrename.c @@ -986,15 +986,18 @@ regrename_do_replace (struct du_head *head, int regno) head->nregs = hard_regno_nregs[regno][mode]; /* SBF: also update the current df info, move from base_regno -> regno. */ - for (chain = head->first; chain; chain = chain->next_use) - { - /* undo regno patch - will be patched again */ - if (REGNO (*chain->loc) == regno) - SET_REGNO(*chain->loc, base_regno); - df_ref_change_reg_with_loc (*chain->loc, regno); + if (base_regno < FIRST_PSEUDO_REGISTER && regno < FIRST_PSEUDO_REGISTER) + for (chain = head->first; chain; chain = chain->next_use) + { + if (DEBUG_INSN_P (chain->insn)) + continue; + /* undo regno patch - will be patched again */ + if (REGNO (*chain->loc) == regno) + SET_REGNO(*chain->loc, base_regno); + df_ref_change_reg_with_loc (*chain->loc, regno); - SET_REGNO(*chain->loc, regno); - } + SET_REGNO(*chain->loc, regno); + } /* Mark the old regno as no longer used. */ if (!df->hard_regs_live_count[base_regno]) From 5844c3b50f6c2e52c83592a41e570603450d47b4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 22 Mar 2017 15:48:28 +0100 Subject: [PATCH 036/303] @B decrement ref count correctly --- gcc/df-scan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc/df-scan.c b/gcc/df-scan.c index b0ef0813d07d..1f23452afe19 100644 --- gcc/df-scan.c +++ gcc/df-scan.c @@ -1809,8 +1809,7 @@ df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df, if (DF_REF_FLAGS_IS_SET(the_ref, DF_HARD_REG_LIVE)) { - if (DF_REF_REGNO(the_ref) < FIRST_PSEUDO_REGISTER) - --df->hard_regs_live_count[DF_REF_REGNO(the_ref)]; + --df->hard_regs_live_count[DF_REF_REGNO(the_ref)]; ++df->hard_regs_live_count[new_regno]; } From e9a9e3005a6160dc5e9a4338c5516f3787e657da Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 22 Mar 2017 15:49:15 +0100 Subject: [PATCH 037/303] @I cleanup --- gcc/regrename.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/gcc/regrename.c b/gcc/regrename.c index 4a9b4c2735a1..2dd96db5b87f 100644 --- gcc/regrename.c +++ gcc/regrename.c @@ -356,8 +356,8 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, { bool has_preferred_class; enum reg_class preferred_class; - int pass; int best_new_reg = old_reg; + int new_reg; /* Further narrow the set of registers we can use for renaming. If the chain needs a call-saved register, mark the call-used @@ -387,30 +387,26 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, If PREFERRED_CLASS is NO_REGS, we iterate over all registers in ascending order without any preference. */ has_preferred_class = (preferred_class != NO_REGS); + for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++) { - int new_reg; - for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++) - { - if (has_preferred_class - && 0 - == TEST_HARD_REG_BIT(reg_class_contents[preferred_class], - new_reg)) - continue; + if (has_preferred_class + && !TEST_HARD_REG_BIT(reg_class_contents[preferred_class], + new_reg)) + continue; - if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable)) - continue; + if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable)) + continue; - if (!best_rename) - return new_reg; + if (!best_rename) + return new_reg; - /* In the first pass, we force the renaming of registers that - don't belong to PREFERRED_CLASS to registers that do, even - though the latters were used not very long ago. - Also use a register if no best_new_reg was found till now */ - if ((tick[best_new_reg] > tick[new_reg] - || (old_reg == best_new_reg && new_reg < old_reg))) - best_new_reg = new_reg; - } + /* In the first pass, we force the renaming of registers that + don't belong to PREFERRED_CLASS to registers that do, even + though the latters were used not very long ago. + Also use a register if no best_new_reg was found till now */ + if ((tick[best_new_reg] > tick[new_reg] + || (old_reg == best_new_reg && new_reg < old_reg))) + best_new_reg = new_reg; } return best_new_reg; } @@ -989,7 +985,7 @@ regrename_do_replace (struct du_head *head, int regno) if (base_regno < FIRST_PSEUDO_REGISTER && regno < FIRST_PSEUDO_REGISTER) for (chain = head->first; chain; chain = chain->next_use) { - if (DEBUG_INSN_P (chain->insn)) + if (DEBUG_INSN_P (chain->insn) && VAR_LOC_UNKNOWN_P(INSN_VAR_LOCATION_LOC(chain->insn))) continue; /* undo regno patch - will be patched again */ if (REGNO (*chain->loc) == regno) From ed41bbc9c042c73e2c423a93d98b6c83988fc8e3 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 22 Mar 2017 16:02:57 +0100 Subject: [PATCH 038/303] @R -ftree-loop-vectorize and -ftree-slp-vectorize are no longer enabled with -O3 --- gcc/opts.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/opts.c b/gcc/opts.c index 0f9431a0b323..28a617c0f14f 100644 --- gcc/opts.c +++ gcc/opts.c @@ -530,8 +530,10 @@ static const struct default_options default_options_table[] = { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 }, { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 }, { OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 }, +#ifndef TARGET_AMIGA { OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 }, { OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 }, +#endif { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC }, { OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 }, { OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 }, From 25f75fe3179ceb6da6f50b1c30d8fe810c1ccccd Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 22 Mar 2017 16:05:51 +0100 Subject: [PATCH 039/303] @N added a new combine optimization.i2 something -> regi3 reg -> somewherewithi4 compare reg, const_0is replaced with: something -> somewhere, if the reg is dead at the comparison --- gcc/combine.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/gcc/combine.c b/gcc/combine.c index 75c6229766c0..333f8fef9655 100644 --- gcc/combine.c +++ gcc/combine.c @@ -102,6 +102,7 @@ along with GCC; see the file COPYING3. If not see #include "valtrack.h" #include "rtl-iter.h" #include "print-rtl.h" +#include "conditions.h" #ifndef LOAD_EXTEND_OP #define LOAD_EXTEND_OP(M) UNKNOWN @@ -2578,6 +2579,7 @@ static rtx_insn * try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, int *new_direct_jump_p, rtx_insn *last_combined_insn) { + rtx_insn * del4 = 0; /* New patterns for I3 and I2, respectively. */ rtx newpat, newi2pat = 0; rtvec newpat_vec_with_clobbers = 0; @@ -3350,6 +3352,52 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, substed_i0 = 1; } +#if HAVE_cc0 + /* SBF: This is an attempt to combine + * i2 something -> reg + * i3 reg -> somewhere + * with the next insn i4 + * i4 compare reg, 0 + * + * then + * newpat = something -> somewhere + * + * If the comparison with 0 is already done in the insn newpat + * and the reg is dead at the compare insn + * then perform the combine and mark the compare as deleted. + */ + if (i2dest_killed && !i0 && !i1 && i2pat && i2_is_used + added_sets_2 > 1 + && NEXT_INSN(i3)) + { + rtx_insn *next = NEXT_INSN(i3); + rtx setn = single_set(next); + if (setn) + { + rtx srcn = SET_SRC(setn); + if (GET_CODE(srcn) == COMPARE) + { + rtx dstn = XEXP(srcn, 0); + srcn = XEXP(srcn, 1); + + if (CONST_INT_P(srcn) && INTVAL(srcn) == 0 + && find_reg_note(next, REG_DEAD, dstn)) + { + /* now check via NOTICE_UPDATE_CC*/ + NOTICE_UPDATE_CC(PATTERN(i2), i2); + if (cc_status.flags == 0 && rtx_equal_p(dstn, cc_status.value1)) + { + added_sets_2 = 0; + i2_is_used = 0; + + /* perform deletion later, if all other checks are ok. */ + del4 = next; + } + } + } + } + } +#endif + /* Fail if an autoincrement side-effect has been duplicated. Be careful to count all the ways that I2SRC and I1SRC can be used. */ if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0 @@ -4387,6 +4435,18 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, move_deaths (newi2pat, NULL_RTX, from_luid, i2, &midnotes); move_deaths (newpat, newi2pat, from_luid, i3, &midnotes); + /* SBF: perform the deletion of the next insn, if marked. */ + if (del4) + { + int del_from_luid = DF_INSN_LUID(del4); + LOG_LINKS(del4) = NULL; + REG_NOTES(del4) = 0; + SET_INSN_DELETED(del4); + if (newi2pat) + move_deaths(newi2pat, NULL_RTX, del_from_luid, del4, &midnotes); + move_deaths(newpat, NULL_RTX, del_from_luid, del4, &midnotes); + } + /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */ if (i3notes) distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL, From 464f34464d1abdb6e5dfcab0e78e12e15ca133b5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Mar 2017 16:12:37 +0100 Subject: [PATCH 040/303] @B added further constraints to optimize the compare away --- gcc/combine.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gcc/combine.c b/gcc/combine.c index 333f8fef9655..1103521f9cf1 100644 --- gcc/combine.c +++ gcc/combine.c @@ -2598,7 +2598,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, I2 and not in I3, a REG_DEAD note must be made. */ rtx i3dest_killed = 0; /* SET_DEST and SET_SRC of I2, I1 and I0. */ - rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0; + rtx i3src = 0, i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0; /* Copy of SET_SRC of I1 and I0, if needed. */ rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0; /* Set if I2DEST was reused as a scratch register. */ @@ -2632,6 +2632,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, if (i1 == i2 || i0 == i2 || (i0 && i0 == i1)) return 0; + if (single_set(i3)) + i3src = SET_SRC(single_set(i3)); + /* Only try four-insn combinations when there's high likelihood of success. Look for simple insns, such as loads of constants or binary operations involving a constant. */ @@ -3367,6 +3370,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, * then perform the combine and mark the compare as deleted. */ if (i2dest_killed && !i0 && !i1 && i2pat && i2_is_used + added_sets_2 > 1 + && rtx_equal_p(i2dest, i3src) && NEXT_INSN(i3)) { rtx_insn *next = NEXT_INSN(i3); @@ -3391,7 +3395,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, /* perform deletion later, if all other checks are ok. */ del4 = next; - } + } } } } @@ -4438,10 +4442,13 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, /* SBF: perform the deletion of the next insn, if marked. */ if (del4) { +// rtx set = SET_SRC(single_set(del4)); + int del_from_luid = DF_INSN_LUID(del4); LOG_LINKS(del4) = NULL; REG_NOTES(del4) = 0; - SET_INSN_DELETED(del4); + SET_INSN_DELETED(del4); +// XEXP(set, 0) = XEXP(set, 1); if (newi2pat) move_deaths(newi2pat, NULL_RTX, del_from_luid, del4, &midnotes); move_deaths(newpat, NULL_RTX, del_from_luid, del4, &midnotes); From 704efeb80a44bf883699e620c4b51eef32d9659c Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 24 Mar 2017 17:05:33 +0100 Subject: [PATCH 041/303] @N support -ramiga-... stuff --- gcc/config/m68k/amigaos.opt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 4d9a42052355..f985cf5e2845 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -7,6 +7,18 @@ noixemul Target RejectNegative Do not use ixemul.library - use libnix instead to link +ramiga-lib +Target RejectNegative +Use libinit.o as start file + +ramiga-libr +Target RejectNegative +Use libinitr.o as start file + +ramiga-dev +Target RejectNegative +Use devinit.o as start file + msmall-code Target RejectNegative Var(flag_smallcode,1) small code model From d62a4d349a55a59aa9d8b9a3f02827d66be960b4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 24 Mar 2017 17:06:31 +0100 Subject: [PATCH 042/303] @R make exception section name configurable by TARGET --- gcc/config/m68k/m68kamigaos.h | 6 ++++++ gcc/except.c | 4 ++-- gcc/target-def.h | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 74403a50bb67..ececc6d76498 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -601,3 +601,9 @@ extern int amiga_is_const_pic_ref(const_rtx x); ! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X)) // (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) || + +#undef TARGET_GCC_EXCEPT_TABLE +#define TARGET_GCC_EXCEPT_TABLE ".data" + +#undef TARGET_GCC_EXCEPT_TABLE_S +#define TARGET_GCC_EXCEPT_TABLE_S ".data" diff --git a/gcc/except.c b/gcc/except.c index 2a1073f80cc4..156d7b76d249 100644 --- gcc/except.c +++ gcc/except.c @@ -2850,14 +2850,14 @@ switch_to_exception_section (const char * ARG_UNUSED (fnname)) it linkonce if we have COMDAT groups to tie them together. */ if (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP) flags |= SECTION_LINKONCE; - sprintf (section_name, ".gcc_except_table.%s", fnname); + sprintf (section_name, TARGET_GCC_EXCEPT_TABLE_S, fnname); s = get_section (section_name, flags, current_function_decl); free (section_name); } else #endif exception_section - = s = get_section (".gcc_except_table", flags, NULL); + = s = get_section (TARGET_GCC_EXCEPT_TABLE, flags, NULL); } else exception_section diff --git a/gcc/target-def.h b/gcc/target-def.h index ec5e09e568e6..9fbfde121095 100644 --- gcc/target-def.h +++ gcc/target-def.h @@ -108,3 +108,11 @@ #include "hooks.h" #include "targhooks.h" #include "insn-target-def.h" + +#ifndef TARGET_GCC_EXCEPT_TABLE +#define TARGET_GCC_EXCEPT_TABLE ".gcc_except_table" +#endif + +#ifndef TARGET_GCC_EXCEPT_TABLE_S +#define TARGET_GCC_EXCEPT_TABLE_S ".gcc_except_table.%s" +#endif From bd6fbbbc0a587184db27e691e05a795e1abdeaf6 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 24 Mar 2017 17:07:18 +0100 Subject: [PATCH 043/303] @R build libstdc++-v3 with noiexmul --- libstdc++-v3/configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 44ba3aca42af..d61b41b2fb7c 100755 --- libstdc++-v3/configure +++ libstdc++-v3/configure @@ -8636,6 +8636,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + enable_shared=no + CXXFLAGS="$CXXFLAGS -noixemul" ;; esac ;; From f05e1e6bd5a30ee7dfea2399acf268771c986767 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Mar 2017 23:11:55 +0100 Subject: [PATCH 044/303] @R move all EH data into .text section --- gcc/config/m68k/m68kamigaos.h | 7 +++++-- gcc/dwarf2out.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index ececc6d76498..68f3277bd87c 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -603,7 +603,10 @@ extern int amiga_is_const_pic_ref(const_rtx x); // (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) || #undef TARGET_GCC_EXCEPT_TABLE -#define TARGET_GCC_EXCEPT_TABLE ".data" +#define TARGET_GCC_EXCEPT_TABLE ".text" #undef TARGET_GCC_EXCEPT_TABLE_S -#define TARGET_GCC_EXCEPT_TABLE_S ".data" +#define TARGET_GCC_EXCEPT_TABLE_S ".text" + +#define EH_TABLES_CAN_BE_READ_ONLY 1 + diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 995ae7f18758..2740e417b0b2 100644 --- gcc/dwarf2out.c +++ gcc/dwarf2out.c @@ -451,7 +451,7 @@ switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED) /*global=*/1); lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); - flags = ((! flag_pic + flags = (( (!flag_pic || flag_pic > 2) || ((fde_encoding & 0x70) != DW_EH_PE_absptr && (fde_encoding & 0x70) != DW_EH_PE_aligned && (per_encoding & 0x70) != DW_EH_PE_absptr From 3be02d432149821fde6d3de2eca3830943c9dfc1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 26 Mar 2017 20:49:43 +0200 Subject: [PATCH 045/303] @R patches to work with amigaos-*-m68k --- libstdc++-v3/configure.host | 5 +++++ libstdc++-v3/include/c_global/cstdio | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host index 304a7f5aff61..354b1c7ead46 100644 --- libstdc++-v3/configure.host +++ libstdc++-v3/configure.host @@ -226,6 +226,11 @@ case "${host_os}" in os_include_dir="os/generic" atomicity_dir="cpu/generic" ;; + amiga*) + os_include_dir="os/newlib" + CXXFLAGS="${CXXFLAGS} -noixemul" + CPPFLAGS="${CPPFLAGS} -noixemul" + ;; bsd*) # Plain BSD attempts to share FreeBSD files. os_include_dir="os/bsd/freebsd" diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio index 522d065d4dc6..86d524f96a62 100644 --- libstdc++-v3/include/c_global/cstdio +++ libstdc++-v3/include/c_global/cstdio @@ -149,9 +149,7 @@ namespace std #if _GLIBCXX_USE_C99_STDIO #undef snprintf -#ifndef AMIGA #undef vfscanf -#endif #undef vscanf #undef vsnprintf #undef vsscanf From 1a1c3869ddd0e8e75eef0849dcd0b060dd26cbbd Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 26 Mar 2017 20:50:20 +0200 Subject: [PATCH 046/303] @R patches to work with amigaos-*-m68k --- libobjc/configure | 3 ++- libobjc/objc/objc.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libobjc/configure b/libobjc/configure index 55fcc33dbe2d..a60258f422d8 100755 --- libobjc/configure +++ libobjc/configure @@ -7637,7 +7637,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + #lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + enable_shared=no ;; esac ;; diff --git a/libobjc/objc/objc.h b/libobjc/objc/objc.h index 37391a446bb0..6c73f53290e8 100644 --- libobjc/objc/objc.h +++ libobjc/objc/objc.h @@ -52,7 +52,11 @@ extern "C" { Important: this could change and we could switch to 'typedef bool BOOL' in the future. Do not depend on the type of BOOL. */ #undef BOOL +#ifdef AMIGA +typedef short BOOL; +#else typedef unsigned char BOOL; +#endif #define YES (BOOL)1 #define NO (BOOL)0 From 7f8948f412f79fb2efd6835a3062720c1b34febf Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 29 Mar 2017 18:08:05 +0200 Subject: [PATCH 047/303] @B fix for possible corrupted code, due to combine optimization. Maybe incorrect... --- gcc/reload1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/reload1.c b/gcc/reload1.c index c2800f8cb790..7f386a3aaab0 100644 --- gcc/reload1.c +++ gcc/reload1.c @@ -7943,7 +7943,8 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j) AUTO_INC reload if reload_out is set but reload_out_reg isn't. */ && (! reload_inherited[j] || (rl->out && ! rl->out_reg)) && ! rtx_equal_p (reg_rtx, old) - && reg_rtx != 0) + && reg_rtx != 0 + && rl->in_reg != rl->out_reg) emit_input_reload_insns (chain, rld + j, old, j); /* When inheriting a wider reload, we have a MEM in rl->in, From 709da5eaf06c7d9d1aa3332feab227469be4cc48 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 30 Mar 2017 11:29:16 +0200 Subject: [PATCH 048/303] @B remove optimization The side effects are not solved yet, so this experiment is removed from the 'stable' branch --- gcc/combine.c | 69 +---------------------------------------------------------- gcc/reload1.c | 3 +-- 2 files changed, 2 insertions(+), 70 deletions(-) diff --git a/gcc/combine.c b/gcc/combine.c index 1103521f9cf1..75c6229766c0 100644 --- gcc/combine.c +++ gcc/combine.c @@ -102,7 +102,6 @@ along with GCC; see the file COPYING3. If not see #include "valtrack.h" #include "rtl-iter.h" #include "print-rtl.h" -#include "conditions.h" #ifndef LOAD_EXTEND_OP #define LOAD_EXTEND_OP(M) UNKNOWN @@ -2579,7 +2578,6 @@ static rtx_insn * try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, int *new_direct_jump_p, rtx_insn *last_combined_insn) { - rtx_insn * del4 = 0; /* New patterns for I3 and I2, respectively. */ rtx newpat, newi2pat = 0; rtvec newpat_vec_with_clobbers = 0; @@ -2598,7 +2596,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, I2 and not in I3, a REG_DEAD note must be made. */ rtx i3dest_killed = 0; /* SET_DEST and SET_SRC of I2, I1 and I0. */ - rtx i3src = 0, i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0; + rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0; /* Copy of SET_SRC of I1 and I0, if needed. */ rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0; /* Set if I2DEST was reused as a scratch register. */ @@ -2632,9 +2630,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, if (i1 == i2 || i0 == i2 || (i0 && i0 == i1)) return 0; - if (single_set(i3)) - i3src = SET_SRC(single_set(i3)); - /* Only try four-insn combinations when there's high likelihood of success. Look for simple insns, such as loads of constants or binary operations involving a constant. */ @@ -3355,53 +3350,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, substed_i0 = 1; } -#if HAVE_cc0 - /* SBF: This is an attempt to combine - * i2 something -> reg - * i3 reg -> somewhere - * with the next insn i4 - * i4 compare reg, 0 - * - * then - * newpat = something -> somewhere - * - * If the comparison with 0 is already done in the insn newpat - * and the reg is dead at the compare insn - * then perform the combine and mark the compare as deleted. - */ - if (i2dest_killed && !i0 && !i1 && i2pat && i2_is_used + added_sets_2 > 1 - && rtx_equal_p(i2dest, i3src) - && NEXT_INSN(i3)) - { - rtx_insn *next = NEXT_INSN(i3); - rtx setn = single_set(next); - if (setn) - { - rtx srcn = SET_SRC(setn); - if (GET_CODE(srcn) == COMPARE) - { - rtx dstn = XEXP(srcn, 0); - srcn = XEXP(srcn, 1); - - if (CONST_INT_P(srcn) && INTVAL(srcn) == 0 - && find_reg_note(next, REG_DEAD, dstn)) - { - /* now check via NOTICE_UPDATE_CC*/ - NOTICE_UPDATE_CC(PATTERN(i2), i2); - if (cc_status.flags == 0 && rtx_equal_p(dstn, cc_status.value1)) - { - added_sets_2 = 0; - i2_is_used = 0; - - /* perform deletion later, if all other checks are ok. */ - del4 = next; - } - } - } - } - } -#endif - /* Fail if an autoincrement side-effect has been duplicated. Be careful to count all the ways that I2SRC and I1SRC can be used. */ if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0 @@ -4439,21 +4387,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, move_deaths (newi2pat, NULL_RTX, from_luid, i2, &midnotes); move_deaths (newpat, newi2pat, from_luid, i3, &midnotes); - /* SBF: perform the deletion of the next insn, if marked. */ - if (del4) - { -// rtx set = SET_SRC(single_set(del4)); - - int del_from_luid = DF_INSN_LUID(del4); - LOG_LINKS(del4) = NULL; - REG_NOTES(del4) = 0; - SET_INSN_DELETED(del4); -// XEXP(set, 0) = XEXP(set, 1); - if (newi2pat) - move_deaths(newi2pat, NULL_RTX, del_from_luid, del4, &midnotes); - move_deaths(newpat, NULL_RTX, del_from_luid, del4, &midnotes); - } - /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */ if (i3notes) distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL, diff --git a/gcc/reload1.c b/gcc/reload1.c index 7f386a3aaab0..c2800f8cb790 100644 --- gcc/reload1.c +++ gcc/reload1.c @@ -7943,8 +7943,7 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j) AUTO_INC reload if reload_out is set but reload_out_reg isn't. */ && (! reload_inherited[j] || (rl->out && ! rl->out_reg)) && ! rtx_equal_p (reg_rtx, old) - && reg_rtx != 0 - && rl->in_reg != rl->out_reg) + && reg_rtx != 0) emit_input_reload_insns (chain, rld + j, old, j); /* When inheriting a wider reload, we have a MEM in rl->in, From c44d7bced301829dbab55b307545a7e029e69e6f Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 30 Mar 2017 20:44:57 +0200 Subject: [PATCH 049/303] @N added a separate optimization pass --- gcc/Makefile.in | 1 + gcc/bbb-opts.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/passes.c | 27 ++++ gcc/passes.def | 1 + gcc/regrename.c | 9 +- gcc/tree-pass.h | 1 + 6 files changed, 437 insertions(+), 3 deletions(-) create mode 100755 gcc/bbb-opts.c mode change 100644 => 100755 gcc/regrename.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 575d308907cc..dc01aeef0f0c 100644 --- gcc/Makefile.in +++ gcc/Makefile.in @@ -1199,6 +1199,7 @@ OBJS = \ auto-inc-dec.o \ auto-profile.o \ bb-reorder.o \ + bbb-opts.o \ bitmap.o \ bt-load.o \ builtins.o \ diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c new file mode 100755 index 000000000000..ff447c9e335e --- /dev/null +++ gcc/bbb-opts.c @@ -0,0 +1,401 @@ +/* Bebbo's Optimizations. + Copyright (C) 2010-2016 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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 3, or (at your option) any later + version. + + GCC 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 GCC; see the file COPYING3. If not see + . */ + +/** + * SBF (Stefan "Bebbo" Franke): + * + * This pass performs multiple optimizations. + * + * #1 propagate_moves + * check if a->b->a can be moved out of a loop. + * + * #2 strcpy + * move a,reg + * move reg,b + * cmp #0,reg + * jne/jeq + */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "target.h" +#include "rtl.h" +#include "df.h" +#include "tm_p.h" +#include "insn-config.h" +#include "recog.h" +#include "cfgrtl.h" +#include "emit-rtl.h" +#include "tree-pass.h" +#include "conditions.h" +#include +#include + +extern void +dump_insns (char const * name); + +/* + * #1 propagate a->b->a moves out of a loop. + * + * consider a loop: + * + * .L1 + * ... + * move d0, a0 ; (1) + * ... + * move xy, (a0)+ + * ... + * move a0, d0 ; (2) + * ... + * jxx .L1 + * + * Then the statements (1) and (2) can be moved out of the loop: + * + * move d0, a0 ; (3) + * .L1 + * ... + * move *, (a0)+ ; a0 is modified somehow + * ... + * jxx .L1 + * move a0, d0 ; (4) + * + * if all criteria are met: + * + * a) no other jump to .L1 -> (LABEL_NUSES(insn) == 1) + * b) no other use of d0 inside the loop + * c) no other use of a0 before (1) + * d) no other use of a1 after (2) + * + * Optional: + * - omit (4) if d0 is dead + * + * this will e.g. convert + .L6: + move.l d0,a1 + move.b (a1)+,d1 + move.l a1,d0 + move.b d1,(a0)+ + cmp.b #0, d1 + jne .L6 + * to + move.l d0,a1 + .L6: + move.b (a1)+,d1 + move.b d1,(a0)+ + cmp.b #0, d1 + jne .L6 + * + */ +static int +propagate_moves () +{ + rtx_insn *insn, *next; + rtx_insn * current_label = 0; + int change_count = 0; + std + ::vector reg_reg; + + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + + if (DEBUG_INSN_P(insn)) + continue; + + if (LABEL_P(insn)) + { + if (LABEL_NUSES(insn) == 1) + { + current_label = insn; + reg_reg.clear (); + } + else + current_label = 0; + } + + if (current_label == 0) + continue; + + if (NONJUMP_INSN_P(insn)) + { + // check for set reg, reg + rtx set = single_set (insn); + if (set) + { + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); + if (REG_P(src) && REG_P(dst)) + reg_reg.push_back (insn); + } + continue; + } + + if (JUMP_P(insn)) + { + if (JUMP_LABEL (insn) == current_label && reg_reg.size () > 1) + { + /* Search for reg/reg pairs. */ + for (auto i = reg_reg.begin (); + i != reg_reg.end () && i + 1 != reg_reg.end ();) + { + bool inc = true; + for (auto j = i + 1; j != reg_reg.end ();) + { + rtx seti = single_set (*i); + rtx srci = SET_SRC(seti); + rtx dsti = SET_DEST(seti); + rtx setj = single_set (*j); + rtx srcj = SET_SRC(setj); + rtx dstj = SET_DEST(setj); + + if (rtx_equal_p (srci, dstj) && rtx_equal_p (srcj, dsti)) + { + /* Ensure correct usage. */ + if (!reg_used_between_p (srci, current_label, *i) + && !reg_used_between_p (srci, *i, *j) + && !reg_used_between_p (srci, *j, insn) + && !reg_used_between_p (dsti, current_label, *i) + && !reg_used_between_p (dsti, *j, insn)) + { + fprintf (stderr, + "condition met, moving regs %d, %d\n", + REGNO(srci), REGNO(dsti)); + + /* Move out of loop. */ + remove_insn (*i); + if (PREV_INSN (current_label)) + add_insn_after (*i, PREV_INSN (current_label), + 0); + else + add_insn_before (*i, current_label, 0); + + remove_insn (*j); + add_insn_after (*j, insn, 0); + + reg_reg.erase (j); + reg_reg.erase (i); + j = reg_reg.end (); + inc = false; + + ++change_count; + } + } + if (inc) + ++j; + } + if (inc) + ++i; + } + } + current_label = 0; + } + } + + return change_count; +} + +/** + * Search for + * + * mov x,reg + * mov reg,x + * cmp #0, reg + * jxx + * + * patterns. + * + * Use a simple state machine to find the patterns. + */ +static void +opt_strcpy () +{ + rtx_insn *insn, *next; + rtx_insn * x2reg = 0; + rtx_insn * reg2x; + unsigned int regno; + + for (insn = get_insns (); insn; insn = next) + { + rtx src; + + next = NEXT_INSN (insn); + + if (NONJUMP_INSN_P(insn)) + { + rtx set = single_set (insn); + if (!set) + continue; + + if (x2reg && reg2x) + { + src = SET_SRC(set); + if (GET_CODE(src) == COMPARE) + { + rtx dst = XEXP(src, 0); + src = XEXP(src, 1); + + if (CONST_INT_P(src) && INTVAL(src) == 0 + && find_reg_note (insn, REG_DEAD, dst)) + { + /* now check via NOTICE_UPDATE_CC*/ + NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x); + if (cc_status.flags == 0 + && rtx_equal_p (dst, cc_status.value2)) + { + int num_clobbers_to_add = 0; + int insn_code_number; + + SET_SRC(single_set(reg2x)) = SET_SRC( + single_set (x2reg)); + insn_code_number = recog (PATTERN (reg2x), reg2x, + &num_clobbers_to_add); + + if (insn_code_number < 0) + { + /* restore register. */ + SET_SRC(single_set(reg2x)) = SET_DEST( + single_set (x2reg)); + } + else + { + + rtx link; + + fprintf ( + stderr, + "condition met, removing compare and joining insns - omit reg %d\n", + REGNO(dst)); + + for (link = REG_NOTES(x2reg); link; + link = XEXP(link, 1)) + if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) + { + if (GET_CODE (link) == EXPR_LIST) + add_reg_note ( + reg2x, REG_NOTE_KIND(link), + copy_insn_1 (XEXP(link, 0))); + else + add_shallow_copy_of_reg_note (reg2x, + link); + } + + SET_INSN_DELETED(x2reg); + SET_INSN_DELETED(insn); + + df_insn_rescan (reg2x); + + } + } + } + x2reg = 0; + continue; + } + reg2x = 0; + } + + /* check for reg2x first, maybe fallback to x2reg. */ + if (x2reg && reg2x == 0) + { + if (REG_P(SET_SRC(set)) && REGNO(SET_SRC(set)) == regno) + { + reg2x = insn; + continue; + } + x2reg = 0; + } + + /* check for a match for x2reg. */ + if (x2reg == 0) + { + if (REG_P(SET_DEST(set))) + { + x2reg = insn; + reg2x = 0; + regno = REGNO(SET_DEST(set)); + } + } + } + } +} + +/* Main entry point to the pass. */ + +static unsigned int +execute_bbb_optimizations (void) +{ + df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN); + df_note_add_problem (); + df_analyze (); + +// dump_insns ("bbb 0"); + + propagate_moves (); + + opt_strcpy (); + + dump_insns ("bbb 1"); + + return 0; +} + +namespace + { + + const pass_data pass_data_bbb_optimizations = + { + RTL_PASS, /* type */ + "bbb", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_NONE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + ( TODO_df_finish | TODO_df_verify ), /* todo_flags_finish */ + }; + + class pass_bbb_optimizations : public rtl_opt_pass + { + public: + pass_bbb_optimizations (gcc::context *ctxt) + : rtl_opt_pass (pass_data_bbb_optimizations, ctxt) + {} + + /* opt_pass methods: */ + virtual bool gate (function *) + { + return true; + } + + virtual unsigned int execute (function *) + { + return execute_bbb_optimizations (); + } + + }; // class pass_bbb_optimizations + + } // anon namespace + +rtl_opt_pass * +make_pass_bbb_optimizations (gcc::context *ctxt) + { + return new pass_bbb_optimizations (ctxt); + } diff --git a/gcc/passes.c b/gcc/passes.c index e89618111245..321adbc61e2d 100644 --- gcc/passes.c +++ gcc/passes.c @@ -2269,6 +2269,31 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status) } +void dump_insns(char const * name) +{ + rtx_insn *insn, *next; + fprintf(stderr, "====================================\npass: %s\n", name); + for (insn = get_insns(); insn; insn = next) + { + next = NEXT_INSN(insn); + debug_rtx(insn); +#if 0 + if (NONJUMP_INSN_P (insn)) + { + rtx x, y, set= single_set (insn); + if (!set) + continue; + x = y = SET_SRC(set); + + while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS) + y = XEXP(y, 0); + if (x != y && REG_P(y) && REGNO(y) == PIC_REG) + debug_rtx(insn); + } +#endif + } +} + /* Execute PASS. */ bool @@ -2278,6 +2303,8 @@ execute_one_pass (opt_pass *pass) bool gate_status; +// dump_insns(pass->name); + /* IPA passes are executed on whole program, so cfun should be NULL. Other passes need function context set. */ if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS) diff --git a/gcc/passes.def b/gcc/passes.def index ec796082ae7f..45ff86c383e4 100644 --- gcc/passes.def +++ gcc/passes.def @@ -446,6 +446,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_split_after_reload); NEXT_PASS (pass_ree); NEXT_PASS (pass_compare_elim_after_reload); + NEXT_PASS (pass_bbb_optimizations); NEXT_PASS (pass_branch_target_load_optimize1); NEXT_PASS (pass_jump2); NEXT_PASS (pass_duplicate_computed_gotos); diff --git a/gcc/regrename.c b/gcc/regrename.c old mode 100644 new mode 100755 index 2dd96db5b87f..4ba825e8d8e8 --- gcc/regrename.c +++ gcc/regrename.c @@ -358,6 +358,7 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, enum reg_class preferred_class; int best_new_reg = old_reg; int new_reg; + int hit = 0; /* Further narrow the set of registers we can use for renaming. If the chain needs a call-saved register, mark the call-used @@ -404,9 +405,11 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, don't belong to PREFERRED_CLASS to registers that do, even though the latters were used not very long ago. Also use a register if no best_new_reg was found till now */ - if ((tick[best_new_reg] > tick[new_reg] - || (old_reg == best_new_reg && new_reg < old_reg))) - best_new_reg = new_reg; + if (new_reg < old_reg || !hit) + { + hit = 1; + best_new_reg = new_reg; + } } return best_new_reg; } diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 5f5055d3a6c1..b3f66ad529b9 100644 --- gcc/tree-pass.h +++ gcc/tree-pass.h @@ -590,6 +590,7 @@ extern rtl_opt_pass *make_pass_branch_target_load_optimize2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_leaf_regs (gcc::context *ctxt); extern rtl_opt_pass *make_pass_split_before_sched2 (gcc::context *ctxt); +extern rtl_opt_pass *make_pass_bbb_optimizations (gcc::context *ctxt); extern rtl_opt_pass *make_pass_compare_elim_after_reload (gcc::context *ctxt); extern rtl_opt_pass *make_pass_sched2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_stack_regs (gcc::context *ctxt); From eb051946c1a720575b80bcd5cf8038710f1c27c1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 31 Mar 2017 11:19:56 +0200 Subject: [PATCH 050/303] @B compiles again with other targets --- gcc/bbb-opts.c | 205 ++++++++++++++++++++++++++++++++++----------------------- gcc/except.c | 1 + 2 files changed, 124 insertions(+), 82 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ff447c9e335e..aeec7a8b4e6a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -107,11 +107,10 @@ dump_insns (char const * name); static int propagate_moves () { + int change_count = 0; rtx_insn *insn, *next; rtx_insn * current_label = 0; - int change_count = 0; - std - ::vector reg_reg; + std::vector reg_reg; for (insn = get_insns (); insn; insn = next) { @@ -153,11 +152,11 @@ propagate_moves () if (JUMP_LABEL (insn) == current_label && reg_reg.size () > 1) { /* Search for reg/reg pairs. */ - for (auto i = reg_reg.begin (); + for (std::vector::iterator i = reg_reg.begin (); i != reg_reg.end () && i + 1 != reg_reg.end ();) { bool inc = true; - for (auto j = i + 1; j != reg_reg.end ();) + for (std::vector::iterator j = i + 1; j != reg_reg.end ();) { rtx seti = single_set (*i); rtx srci = SET_SRC(seti); @@ -208,7 +207,6 @@ propagate_moves () current_label = 0; } } - return change_count; } @@ -224,9 +222,11 @@ propagate_moves () * * Use a simple state machine to find the patterns. */ -static void +static int opt_strcpy () { + int change_count = 0; +#if HAVE_cc0 rtx_insn *insn, *next; rtx_insn * x2reg = 0; rtx_insn * reg2x; @@ -234,106 +234,145 @@ opt_strcpy () for (insn = get_insns (); insn; insn = next) { - rtx src; - next = NEXT_INSN (insn); - if (NONJUMP_INSN_P(insn)) - { - rtx set = single_set (insn); - if (!set) - continue; + if (!NONJUMP_INSN_P(insn)) + continue; + + rtx set = single_set (insn); + if (!set) + continue; - if (x2reg && reg2x) + if (x2reg && reg2x) + { + rtx src = SET_SRC(set); + if (GET_CODE(src) == COMPARE) { - src = SET_SRC(set); - if (GET_CODE(src) == COMPARE) - { - rtx dst = XEXP(src, 0); - src = XEXP(src, 1); + rtx dst = XEXP(src, 0); + src = XEXP(src, 1); - if (CONST_INT_P(src) && INTVAL(src) == 0 - && find_reg_note (insn, REG_DEAD, dst)) + if (CONST_INT_P(src) && INTVAL(src) == 0 + && find_reg_note (insn, REG_DEAD, dst)) + { + /* now check via NOTICE_UPDATE_CC*/ + NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x); + if (cc_status.flags == 0 + && rtx_equal_p (dst, cc_status.value2)) { - /* now check via NOTICE_UPDATE_CC*/ - NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x); - if (cc_status.flags == 0 - && rtx_equal_p (dst, cc_status.value2)) - { - int num_clobbers_to_add = 0; - int insn_code_number; + int num_clobbers_to_add = 0; + int insn_code_number; - SET_SRC(single_set(reg2x)) = SET_SRC( - single_set (x2reg)); - insn_code_number = recog (PATTERN (reg2x), reg2x, - &num_clobbers_to_add); + SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); + insn_code_number = recog (PATTERN (reg2x), reg2x, + &num_clobbers_to_add); - if (insn_code_number < 0) - { - /* restore register. */ - SET_SRC(single_set(reg2x)) = SET_DEST( - single_set (x2reg)); - } - else - { + if (insn_code_number < 0) + { + /* restore register. */ + SET_SRC(single_set(reg2x)) = SET_DEST( + single_set (x2reg)); + } + else + { - rtx link; + rtx link; - fprintf ( - stderr, - "condition met, removing compare and joining insns - omit reg %d\n", - REGNO(dst)); + fprintf ( + stderr, + "condition met, removing compare and joining insns - omit reg %d\n", + REGNO(dst)); - for (link = REG_NOTES(x2reg); link; - link = XEXP(link, 1)) - if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) - { - if (GET_CODE (link) == EXPR_LIST) - add_reg_note ( - reg2x, REG_NOTE_KIND(link), - copy_insn_1 (XEXP(link, 0))); - else - add_shallow_copy_of_reg_note (reg2x, - link); - } + for (link = REG_NOTES(x2reg); link; + link = XEXP(link, 1)) + if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) + { + if (GET_CODE (link) == EXPR_LIST) + add_reg_note (reg2x, REG_NOTE_KIND(link), + copy_insn_1 (XEXP(link, 0))); + else + add_shallow_copy_of_reg_note (reg2x, link); + } - SET_INSN_DELETED(x2reg); - SET_INSN_DELETED(insn); + SET_INSN_DELETED(x2reg); + SET_INSN_DELETED(insn); - df_insn_rescan (reg2x); + df_insn_rescan (reg2x); - } + ++change_count; } } - x2reg = 0; - continue; } - reg2x = 0; + x2reg = 0; + continue; } + reg2x = 0; + } - /* check for reg2x first, maybe fallback to x2reg. */ - if (x2reg && reg2x == 0) + /* check for reg2x first, maybe fallback to x2reg. */ + if (x2reg && reg2x == 0) + { + if (REG_P(SET_SRC(set)) && REGNO(SET_SRC(set)) == regno) { - if (REG_P(SET_SRC(set)) && REGNO(SET_SRC(set)) == regno) - { - reg2x = insn; - continue; - } - x2reg = 0; + reg2x = insn; + continue; } + x2reg = 0; + } - /* check for a match for x2reg. */ - if (x2reg == 0) + /* check for a match for x2reg. */ + if (x2reg == 0) + { + if (REG_P(SET_DEST(set))) { - if (REG_P(SET_DEST(set))) - { - x2reg = insn; - reg2x = 0; - regno = REGNO(SET_DEST(set)); - } + x2reg = insn; + reg2x = 0; + regno = REGNO(SET_DEST(set)); } } } +#endif + return change_count; +} + +/* + * Convert loops using a counting reg as offset with an address reg + * into a loop with auto inc address regs. + */ +static int +offset_2_autoinc (void) +{ + rtx_insn *insn, *next; + rtx_insn * reg_const = 0; + int change_count = 0; + + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + + if (!next || !LABEL_P(next) || LABEL_NUSES(next) != 1) + continue; + + if (!NONJUMP_INSN_P(insn)) + continue; + + rtx set = single_set (insn); + if (!set) + continue; + + rtx reg = SET_DEST(set); + if (!REG_P(reg)) + continue; + + rtx val = SET_SRC(set); + + +// fprintf(stderr, "possible start for offset_2_autoinc\n"); +// debug_rtx(insn); +// debug_rtx(next); + + } + + return change_count; } /* Main entry point to the pass. */ @@ -349,9 +388,11 @@ execute_bbb_optimizations (void) propagate_moves (); + offset_2_autoinc (); + opt_strcpy (); - dump_insns ("bbb 1"); +// dump_insns ("bbb 1"); return 0; } diff --git a/gcc/except.c b/gcc/except.c index 156d7b76d249..194478f8454c 100644 --- gcc/except.c +++ gcc/except.c @@ -142,6 +142,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "builtins.h" #include "tree-hash-traits.h" +#include "target-def.h" static GTY(()) int call_site_base; From 73b869461936fd68a37b9edc8f0e4eba48d5c440 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Apr 2017 16:03:47 +0200 Subject: [PATCH 051/303] @R use a5 instead of fp --- gcc/config/m68k/amigaos.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 7259611edc9e..ce47723e962f 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -153,11 +153,7 @@ amiga_named_section (const char *name, unsigned int flags, tree decl); #define FRAME_POINTER_REGNUM 13 #undef M68K_REGNAME -#define M68K_REGNAME(r) ( \ - ( ((r) == FRAME_POINTER_REGNUM) \ - && frame_pointer_needed) ? \ - M68K_FP_REG_NAME : reg_names[(r)]) - +#define M68K_REGNAME(r) (reg_names[(r)]) /* The AmigaOS ABI does not define how structures should be returned, so, contrary to 'm68k.h', we prefer a multithread-safe solution. */ From 626d238b27f86a4369aeb13ad11153accd414f90 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Apr 2017 16:06:55 +0200 Subject: [PATCH 052/303] @R make MEM_P more expensive than REG_P --- gcc/config/m68k/m68k.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index d60371a92bc6..6c0d9211598d 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2928,6 +2928,17 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code, *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 2 : 3); return true; } + /* reg + value */ +// if (mode == SImode +// && REG_P(XEXP(x, 0))) { +// if (m68k_rtx_costs(XEXP(x, 1), mode, PLUS, 1, total, speed)) +// { +// if (REGNO_REG_CLASS(REGNO(XEXP(x, 0))) == ADDR_REGS) +// *total += 4; +// return true; +// } +// } + return false; case ASHIFT: @@ -2996,6 +3007,25 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code, *total = 0; return false; + case MEM: + { + /* simple but not exact */ + rtx y = XEXP(x, 0); + int yc = GET_CODE(y); + if (yc == REG || yc == PRE_INC || yc == POST_INC || yc == POST_DEC) + *total += 4; + else + if (yc == PRE_DEC) + *total += 6; + else + *total += 8; + + if (mode != QImode && mode != QImode) + *total += 4; + + return true; + } + default: return false; } From 9c9c8b4c31a9ed000a27ff22245ad21b7ad21e67 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Apr 2017 16:08:30 +0200 Subject: [PATCH 053/303] @R added reg life analysis to own optimizer --- gcc/bbb-opts.c | 793 ++++++++++++++++++++++++++++++++++++++++++++++++--------- gcc/passes.def | 1 + 2 files changed, 672 insertions(+), 122 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index aeec7a8b4e6a..7fd01139d0f3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -25,11 +25,16 @@ * #1 propagate_moves * check if a->b->a can be moved out of a loop. * - * #2 strcpy + * #2 strcpy_opt * move a,reg * move reg,b * cmp #0,reg - * jne/jeq + * jcc + * + * -> + * move a,b + * jcc + * */ #include "config.h" @@ -49,8 +54,285 @@ #include #include -extern void -dump_insns (char const * name); +/* enough for m68k. */ +typedef unsigned insn_info; //[(FIRST_PSEUDO_REGISTER + sizeof(unsigned) * 8 - 1) / (sizeof(unsigned) * 8)]; + +static inline void +resetii (unsigned & ii) +{ + ii = 0; +} + +static inline void +setii (unsigned regno, unsigned & ii) +{ + ii |= 1 << regno; +} + +static inline void +clearii (unsigned regno, unsigned & ii) +{ + ii &= ~(1 << regno); +} + +static inline bool +getii (unsigned regno, unsigned & ii) +{ + return ii & (1 << regno) ? true : false; +} + +/* scan rtx for registers. */ +static void +scanii (rtx x, unsigned & ii) +{ + if (REG_P(x)) + { + setii (REGNO(x), ii); + return; + } + + RTX_CODE code = GET_CODE(x); + const char *fmt = GET_RTX_FORMAT(code); + for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + scanii (XEXP(x, i), ii); + else if (fmt[i] == 'E') + for (int j = XVECLEN (x, i) - 1; j >= 0; j--) + scanii (XVECEXP(x, i, j), ii); + } +} + +static std::vector insns; +static std::vector jumps; +static std::map insn2index; +static std::vector infos; + +static void +clear (void) +{ + insns.clear (); + jumps.clear (); + insn2index.clear (); + infos.clear (); +} + +static void +dump_costs (void) +{ + rtx d0 = gen_raw_REG (SImode, 0); + rtx d0b = gen_raw_REG (QImode, 0); + rtx d1 = gen_raw_REG (SImode, 1); + rtx d1b = gen_raw_REG (QImode, 1); + rtx a0 = gen_raw_REG (SImode, 8); + rtx a1 = gen_raw_REG (SImode, 9); + + struct ICO + { + char const * name; + rtx set; + } data[] = + { + { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) }, + { "move a0,d0", gen_rtx_SET(d0, a0) }, + { "move (a0),d0", gen_rtx_SET(d0, gen_rtx_MEM (SImode, a0)) }, + { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) }, + { "move d1,(a1)+", gen_rtx_SET(d1, gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode, a1))) }, + { "move (a0),(a1)", gen_rtx_SET(gen_rtx_MEM (SImode, a1), gen_rtx_MEM (SImode, a0)) }, + { 0, 0 } }, *p; + + for (p = data; p->name; ++p) + { + int cost = insn_rtx_cost (p->set, true); + fprintf (stderr, "%s: %d\n", p->name, cost); + } +} + + +static void +dump_insns (char const * name) +{ + rtx_insn *insn, *next; + fprintf(stderr, "====================================: %s\n", name); + for (unsigned i = 0; i < insns.size(); ++i) + { + insn_info & ii = infos[i]; + + for (int j = 0; j < 8; ++j) + if (getii(j, ii)) + fprintf(stderr, "d%d ", j); + + for (int j = 8; j < 16; ++j) + if (getii(j, ii)) + fprintf(stderr, "a%d ", j-8); + + fprintf(stderr, "\t"); + debug_rtx(insns[i]); + } +} + + +/* + * Create a filtered view of insns - keep only those to work with. + */ +static void +filter_insns () +{ + rtx_insn *insn, *next; + clear (); + + df_insn_rescan_all (); + + /* create a vector with relevant insn. */ + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + + if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn)) + { + // debug_rtx (insn); + if (JUMP_P(insn)) + jumps.push_back(insn); + + insn2index.insert (std::make_pair (insn, insns.size ())); + insns.push_back (insn); + } + } + + /* prepare insn_info */ + insn_info ii; + resetii (ii); + for (unsigned i = 0; i < insns.size (); ++i) + { + infos.push_back (ii); + } + + /* own analyze life */ + std::vector> todo; + todo.push_back (std::make_pair (insns.size () - 1, ii)); + + int pass = 0; + while (!todo.empty ()) + { + std::pair p = *todo.rbegin (); + todo.pop_back (); + + insn_info ii = p.second; + + for (int pos = p.first; pos >= 0; --pos) + { + rtx_insn * insn = insns[pos]; + + if (pass && ii == infos[pos]) + break; + + ii |= infos[pos]; + + if (LABEL_P(insn)) + { + /* work on all jumps referring to that label. */ + for (std::vector::iterator i = jumps.begin (); i != jumps.end (); ++i) + { + if (JUMP_LABEL(*i) == insn) + { + std::map::iterator j = insn2index.find (*i); + if (j != insn2index.end()) + todo.push_back (std::make_pair (j->second, ii)); + } + } + continue; + } + + rtx set = single_set (insn); + if (set == 0) + { + if (JUMP_P(insn)) { + resetii(ii); + setii(0, ii); + infos[pos] = ii; + continue; + } + fprintf(stderr, "##### "); + debug_rtx(insn); + continue; + } + + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); + + debug_rtx(insn); + + if (CALL_P(insn)) + { + /* a call sets d0 and kills d1,a0,a1. */ + if (getii (1, ii)) + fprintf (stderr, "d1 used after call\n"); + if (getii (8, ii)) + fprintf (stderr, "a0 used after call\n"); + if (getii (9, ii)) + fprintf (stderr, "a1 used after call\n"); + + resetii (ii); + // use regs depending on flag mregparm + for (int i = 0; i < amigaos_regparm; ++i) + { + setii (i, ii); + setii (i + 8, ii); + } + + // check for reg use + if (REG_P(src)) + setii (REGNO(src), ii); + + infos[pos] = ii; + continue; + } + + if (JUMP_P(insn)) + { + if (ANY_RETURN_P(src)) + { + resetii (ii); + setii (0, ii); + } + else + { + ii |= infos[pos]; + + // check for reg use + if (REG_P(src)) + setii (REGNO(src), ii); + + } + infos[pos] = ii; + continue; + } + + // scan insn for regs + // a def stop propagation + // a use starts propagation + // also add use to current ii + insn_info use; + resetii (use); + + insn_info def; + resetii (def); + + scanii (src, use); + if (REG_P(dst)) + setii (REGNO(dst), def); + else + scanii (dst, use); + + infos[pos] = use | ii; + + ii &= ~def; + ii |= use; + } + ++pass; + } + +} /* * #1 propagate a->b->a moves out of a loop. @@ -102,29 +384,34 @@ dump_insns (char const * name); move.b d1,(a0)+ cmp.b #0, d1 jne .L6 + * + * Also allow exit jumps, if the modification of the reg is const + * and insert a correction after the exit label. + * The label must only be reachable by the exit jump. */ -static int +static unsigned propagate_moves () { - int change_count = 0; - rtx_insn *insn, *next; + unsigned change_count = 0; rtx_insn * current_label = 0; - std::vector reg_reg; + unsigned current_label_index; + std::vector reg_reg; + std::vector jump_out; - for (insn = get_insns (); insn; insn = next) + /* start at 1 since there must be an insn before the label. */ + for (unsigned index = 1; index < insns.size (); ++index) { - next = NEXT_INSN (insn); - - if (DEBUG_INSN_P(insn)) - continue; + rtx_insn * insn = insns[index]; if (LABEL_P(insn)) { if (LABEL_NUSES(insn) == 1) { current_label = insn; + current_label_index = index; reg_reg.clear (); + jump_out.clear (); } else current_label = 0; @@ -142,59 +429,180 @@ propagate_moves () rtx src = SET_SRC(set); rtx dst = SET_DEST(set); if (REG_P(src) && REG_P(dst)) - reg_reg.push_back (insn); + reg_reg.push_back (index); } + else + current_label = 0; + continue; } if (JUMP_P(insn)) { - if (JUMP_LABEL (insn) == current_label && reg_reg.size () > 1) + rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn); + if (label != current_label) + { + /* collect the labels for a later check if a fixup is possible. */ + if (LABEL_NUSES(label) == 1 && BARRIER_P(PREV_INSN (label))) + jump_out.push_back (label); + else + current_label = 0; + continue; + } + + if (reg_reg.size () > 1) { /* Search for reg/reg pairs. */ - for (std::vector::iterator i = reg_reg.begin (); - i != reg_reg.end () && i + 1 != reg_reg.end ();) + for (std::vector::iterator i = reg_reg.begin (); i != reg_reg.end () && i + 1 != reg_reg.end (); + ) { bool inc = true; - for (std::vector::iterator j = i + 1; j != reg_reg.end ();) + for (std::vector::iterator j = i + 1; j != reg_reg.end ();) { - rtx seti = single_set (*i); + rtx_insn * ii = insns[*i]; + rtx seti = single_set (ii); rtx srci = SET_SRC(seti); rtx dsti = SET_DEST(seti); - rtx setj = single_set (*j); + rtx_insn * jj = insns[*j]; + rtx setj = single_set (jj); rtx srcj = SET_SRC(setj); rtx dstj = SET_DEST(setj); if (rtx_equal_p (srci, dstj) && rtx_equal_p (srcj, dsti)) { /* Ensure correct usage. */ - if (!reg_used_between_p (srci, current_label, *i) - && !reg_used_between_p (srci, *i, *j) - && !reg_used_between_p (srci, *j, insn) - && !reg_used_between_p (dsti, current_label, *i) - && !reg_used_between_p (dsti, *j, insn)) + if (!reg_used_between_p (srci, current_label, ii) && !reg_used_between_p (srci, ii, jj) + && !reg_used_between_p (srci, jj, insn) && !reg_used_between_p (dsti, current_label, ii) + && !reg_used_between_p (dsti, jj, insn)) { - fprintf (stderr, - "condition met, moving regs %d, %d\n", - REGNO(srci), REGNO(dsti)); - - /* Move out of loop. */ - remove_insn (*i); - if (PREV_INSN (current_label)) - add_insn_after (*i, PREV_INSN (current_label), - 0); - else - add_insn_before (*i, current_label, 0); - - remove_insn (*j); - add_insn_after (*j, insn, 0); - - reg_reg.erase (j); - reg_reg.erase (i); - j = reg_reg.end (); - inc = false; - - ++change_count; + std::vector fixups; + + /* if there are jumps out of the loop, + * check if the modification occurs before the jump, + * and if, that it's a plus const. + */ + if (jump_out.size ()) + { + std::vector::iterator label_iter = jump_out.begin (); + int fixup = 0; + fprintf (stderr, "need %d jump out fixups\n", jump_out.size ()); + + for (unsigned k = *i + 1; k != *j; ++k) + { + rtx_insn * check = insns[k]; + if (JUMP_P(check)) + { + fixups.push_back (fixup); + if (++label_iter == jump_out.end ()) + break; + continue; + } + + if (reg_overlap_mentioned_p (dsti, PATTERN (check))) + { + /* right now only support auto_incs. */ + rtx set = single_set (check); + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); + + if (reg_overlap_mentioned_p (dsti, dst)) + { + if (REG_P(dst)) + break; + if (!MEM_P(dst)) + break; + + rtx x = XEXP(dst, 0); + if (GET_CODE(x) == REG) + fixup += 0; // direct use + else if (GET_CODE(x) == PRE_INC || + GET_CODE(x) == POST_INC) + fixup -= GET_MODE_SIZE(GET_MODE(dst)); + else if (GET_CODE(dst) == PRE_DEC || + GET_CODE(dst) == POST_DEC) + fixup += GET_MODE_SIZE(GET_MODE(dst)); + else + break; + } + + if (reg_overlap_mentioned_p (dsti, src)) + { + if (REG_P(src)) + fixup += 0; + else + { + if (!MEM_P(src)) + break; + + rtx x = XEXP(src, 0); + if (GET_CODE(x) == REG) + fixup += 0; // direct use + else if (GET_CODE(x) == PRE_INC || + GET_CODE(x) == POST_INC) + fixup -= GET_MODE_SIZE(GET_MODE(dst)); + else if (GET_CODE(dst) == PRE_DEC || + GET_CODE(dst) == POST_DEC) + fixup += GET_MODE_SIZE(GET_MODE(dst)); + else + break; + } + } + } + } + } + + /* got a fixup for all jump_outs? */ + if (fixups.size () == jump_out.size ()) + { + rtx_insn * before = insns[current_label_index - 1]; + rtx_insn * after = insns[index + 1]; + rtx bset = single_set (before); + + fprintf (stderr, "condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti)); + + /* Move in front of loop and mark as dead. */ + remove_insn (ii); + add_insn_after (ii, before, 0); + add_reg_note (ii, REG_DEAD, srci); + + /* Plus check if the reg was just loaded. */ + if (bset) + { + rtx bdst = SET_DEST(bset); + if (REG_P(bdst) && REGNO(bdst) == REGNO(srci)) + { + SET_DEST(bset) = dsti; + SET_INSN_DELETED(ii); + } + } + + /* Move behind loop - into next BB. */ + remove_insn (jj); + add_insn_before (jj, after, 0); + + reg_reg.erase (j); + reg_reg.erase (i); + j = reg_reg.end (); + inc = false; + + df_insn_rescan (ii); + df_insn_rescan (jj); + + /* add fixes if there were jumps out of the loop. */ + if (jump_out.size ()) + { + fprintf (stderr, "fixing %d jump outs\n", jump_out.size ()); + + for (unsigned k = 0; k < jump_out.size (); ++k) + { + rtx neu = gen_rtx_SET( + dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k]))); + rtx_insn * neui = emit_insn_after (neu, jump_out[k]); + df_insn_rescan (neui); + } + } + ++change_count; + } } } if (inc) @@ -222,19 +630,18 @@ propagate_moves () * * Use a simple state machine to find the patterns. */ -static int +static unsigned opt_strcpy () { - int change_count = 0; + unsigned change_count = 0; #if HAVE_cc0 - rtx_insn *insn, *next; rtx_insn * x2reg = 0; rtx_insn * reg2x; unsigned int regno; - for (insn = get_insns (); insn; insn = next) + for (unsigned index = 0; index < insns.size (); ++index) { - next = NEXT_INSN (insn); + rtx_insn * insn = insns[index]; if (!NONJUMP_INSN_P(insn)) continue; @@ -251,26 +658,22 @@ opt_strcpy () rtx dst = XEXP(src, 0); src = XEXP(src, 1); - if (CONST_INT_P(src) && INTVAL(src) == 0 - && find_reg_note (insn, REG_DEAD, dst)) + if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst)) { /* now check via NOTICE_UPDATE_CC*/ - NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x); - if (cc_status.flags == 0 - && rtx_equal_p (dst, cc_status.value2)) + NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x); + if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2)) { int num_clobbers_to_add = 0; int insn_code_number; SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); - insn_code_number = recog (PATTERN (reg2x), reg2x, - &num_clobbers_to_add); + insn_code_number = recog (PATTERN (reg2x), reg2x, &num_clobbers_to_add); if (insn_code_number < 0) { /* restore register. */ - SET_SRC(single_set(reg2x)) = SET_DEST( - single_set (x2reg)); + SET_SRC(single_set(reg2x)) = SET_DEST(single_set (x2reg)); } else { @@ -278,17 +681,14 @@ opt_strcpy () rtx link; fprintf ( - stderr, - "condition met, removing compare and joining insns - omit reg %d\n", - REGNO(dst)); + stderr, + "condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst)); - for (link = REG_NOTES(x2reg); link; - link = XEXP(link, 1)) + for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1)) if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) { if (GET_CODE (link) == EXPR_LIST) - add_reg_note (reg2x, REG_NOTE_KIND(link), - copy_insn_1 (XEXP(link, 0))); + add_reg_note (reg2x, REG_NOTE_KIND(link), copy_insn_1 (XEXP(link, 0))); else add_shallow_copy_of_reg_note (reg2x, link); } @@ -338,45 +738,165 @@ opt_strcpy () * Convert loops using a counting reg as offset with an address reg * into a loop with auto inc address regs. */ -static int +static unsigned offset_2_autoinc (void) { - rtx_insn *insn, *next; + unsigned change_count = 0; +#if 0 rtx_insn * reg_const = 0; - int change_count = 0; - for (insn = get_insns (); insn; insn = next) + for (unsigned index = 0; index < insns.size (); ++index) { - next = NEXT_INSN (insn); + rtx_insn * insn = insns[index]; if (!next || !LABEL_P(next) || LABEL_NUSES(next) != 1) - continue; + continue; if (!NONJUMP_INSN_P(insn)) - continue; + continue; rtx set = single_set (insn); if (!set) - continue; + continue; rtx reg = SET_DEST(set); if (!REG_P(reg)) - continue; + continue; rtx val = SET_SRC(set); - // fprintf(stderr, "possible start for offset_2_autoinc\n"); -// debug_rtx(insn); -// debug_rtx(next); +// //debug_rtx(insn); +// //debug_rtx(next); } +#endif return change_count; } -/* Main entry point to the pass. */ +/* + * convert + * + * set reg1, plus (reg2, const) + * set mem(reg2), y + * + * -> + * set reg1, reg2 + * set mem(reg1+), y + * + * if size of postinc == const + * + (insn 33 32 35 4 (set (reg/v/f:SI 8 a0 [orig:47 s ] [47]) + (plus:SI (reg/v/f:SI 9 a1 [orig:46 s ] [46]) + (const_int 1 [0x1]))) sn.c:5 141 {*addsi3_internal} + (nil)) + (insn 36 35 37 4 (set (mem:QI (reg/v/f:SI 9 a1 [orig:46 s ] [46]) [0 MEM[base: s_17, offset: 4294967295B]+0 S1 A8]) + (mem:QI (post_inc:SI (reg/v/f:SI 10 a2 [orig:53 s2 ] [53])) [0 MEM[base: s2_19, offset: 4294967295B]+0 S1 A8])) sn.c:5 46 {*m68k.md:1083} + (expr_list:REG_INC (reg/v/f:SI 10 a2 [orig:53 s2 ] [53]) + (nil))) + */ +static unsigned +commute_add_move (void) +{ + unsigned change_count = 0; + + for (unsigned index = 0; index + 1 < insns.size (); ++index) + { + rtx_insn * insn = insns[index]; + rtx set = single_set (insn); + if (!set) + continue; + + rtx reg1 = SET_DEST(set); + if (!REG_P(reg1)) + continue; + + rtx plus = SET_SRC(set); + if (GET_CODE(plus) != PLUS) + continue; + + rtx reg2 = XEXP(plus, 0); + if (!REG_P(reg2)) + continue; + + rtx cnst = XEXP(plus, 1); + if (!CONST_INT_P(cnst)) + continue; + + rtx_insn * next = insns[index + 1]; + rtx set2 = single_set (next); + if (!set2) + continue; + + rtx dst = SET_DEST(set2); + if (!MEM_P(dst) || GET_MODE_SIZE(GET_MODE(dst)) != INTVAL(cnst)) + continue; + + rtx memreg = XEXP(dst, 0); + if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg2)) + continue; + int oldcost1 = insn_rtx_cost (set, true); + int oldcost2 = insn_rtx_cost (set2, true); + + fprintf (stderr, "commute_add_move found, oldcost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2); + + //debug_rtx (insn); + //debug_rtx (next); + + rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1); + rtx newmem = replace_equiv_address_nv (dst, pinc); + + if (validate_change (next, &SET_DEST(set2), newmem, 0)) + { + SET_INSN_DELETED(insn); + + insn = emit_insn_before (gen_movsi (reg1, reg2), next); + + add_reg_note (next, REG_INC, reg1); + + int newcost1 = insn_rtx_cost (set, true); + int newcost2 = insn_rtx_cost (set2, true); + + fprintf (stderr, "commute_add_move found, newcost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2); + + //debug_rtx (insn); + //debug_rtx (next); + + df_insn_rescan (insn); + df_insn_rescan (next); + + ++change_count; + } + } + return change_count; +} + +static unsigned +const_cmp_to_sub (void) +{ + unsigned change_count = 0; +#if HAVE_cc0 + for (unsigned index = 0; index + 1 < insns.size (); ++index) + { + rtx_insn * insn = insns[index]; + rtx set = single_set (insn); + if (!set) + continue; + + rtx dst = SET_DEST(set); + if (dst != cc0_rtx) + continue; + + fprintf (stderr, "cc0:"); + debug_rtx (insn); + } +#endif + return change_count; +} + +/* Main entry point to the pass. */ static unsigned int execute_bbb_optimizations (void) { @@ -385,58 +905,87 @@ execute_bbb_optimizations (void) df_analyze (); // dump_insns ("bbb 0"); + filter_insns (); + + for (;;) + { + int done = 1; + if (propagate_moves ()) + done = 0, filter_insns (); + + if (offset_2_autoinc ()) + done = 0, filter_insns (); - propagate_moves (); + if (opt_strcpy ()) + done = 0, filter_insns (); - offset_2_autoinc (); + if (commute_add_move ()) + done = 0, filter_insns (); - opt_strcpy (); + if (const_cmp_to_sub ()) + done = 0, filter_insns (); -// dump_insns ("bbb 1"); + if (done) + break; + } + + dump_insns ("bbb 1"); + clear (); + + dump_costs (); return 0; } namespace +{ + + const pass_data pass_data_bbb_optimizations = + { RTL_PASS, /* type */ + "bbb", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_NONE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + ( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */ + }; + + class pass_bbb_optimizations : public rtl_opt_pass { + public: + pass_bbb_optimizations (gcc::context *ctxt) : + rtl_opt_pass (pass_data_bbb_optimizations, ctxt) + { + } - const pass_data pass_data_bbb_optimizations = - { - RTL_PASS, /* type */ - "bbb", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - ( TODO_df_finish | TODO_df_verify ), /* todo_flags_finish */ - }; - - class pass_bbb_optimizations : public rtl_opt_pass - { - public: - pass_bbb_optimizations (gcc::context *ctxt) - : rtl_opt_pass (pass_data_bbb_optimizations, ctxt) - {} - - /* opt_pass methods: */ - virtual bool gate (function *) - { - return true; - } - - virtual unsigned int execute (function *) - { - return execute_bbb_optimizations (); - } - - }; // class pass_bbb_optimizations - - } // anon namespace + /* opt_pass methods: */ + virtual bool + gate (function *) + { + return TARGET_AMIGA; + } + + virtual unsigned int + execute (function *) + { + return execute_bbb_optimizations (); + } + + opt_pass * + clone () + { + return new pass_bbb_optimizations (m_ctxt); + } + + }; +// class pass_bbb_optimizations + +}// anon namespace rtl_opt_pass * -make_pass_bbb_optimizations (gcc::context *ctxt) - { - return new pass_bbb_optimizations (ctxt); - } +make_pass_bbb_optimizations (gcc::context * ctxt) +{ + return new pass_bbb_optimizations (ctxt); +} diff --git a/gcc/passes.def b/gcc/passes.def index 45ff86c383e4..ca5b94552d4e 100644 --- gcc/passes.def +++ gcc/passes.def @@ -460,6 +460,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_stack_adjustments); NEXT_PASS (pass_fast_rtl_dce); NEXT_PASS (pass_reorder_blocks); + NEXT_PASS (pass_bbb_optimizations); NEXT_PASS (pass_branch_target_load_optimize2); NEXT_PASS (pass_leaf_regs); NEXT_PASS (pass_split_before_sched2); From a56cbf57c5732afe7dfe0b67472284434ccfcbb2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Apr 2017 22:54:53 +0200 Subject: [PATCH 054/303] @B fix resident options, add -fbbb --- gcc/config/m68k/amigaos.h | 2 +- gcc/config/m68k/amigaos.opt | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index ce47723e962f..49dd90d745c3 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -454,7 +454,7 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*); #define SUBTARGET_OVERRIDE_OPTIONS \ do \ { \ - if (!TARGET_68020 && flag_mybaserel==2) \ + if (!TARGET_68020 && flag_pic==4) \ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \ error ("-mregparm=x with 1 <= x <= %d\n", AMIGAOS_MAX_REGPARM); \ diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index f985cf5e2845..2d8bed0a9103 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -32,13 +32,17 @@ Target Report Var(flag_pic,4) data is adressed relativ to a4 with 32 bit offsets resident -Target Common Report Var(flag_mybaserel,1) +Target Common Report Var(flag_pic,3) data is adressed relativ to a4, linked as resident resident32 -Target Common Report Var(flag_mybaserel,2) +Target Common Report Var(flag_pic,4) data is adressed relativ to a4 with 32 bit offsets, linked as resident mcrt= Target RejectNegative Var(amigaos_crt) Joined -Specify startup binary \ No newline at end of file +Specify startup binary + +fbbb +Target Var(flag_bbb_opts,1) UInteger Init(0) +Enable Bebbo's optimizations From 01bd7d9ab157a9d973115a47cb9d24446f30f619 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Apr 2017 22:55:25 +0200 Subject: [PATCH 055/303] @I cleanup --- gcc/config/m68k/m68k.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 6c0d9211598d..52eabeaafb23 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2928,16 +2928,6 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code, *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 2 : 3); return true; } - /* reg + value */ -// if (mode == SImode -// && REG_P(XEXP(x, 0))) { -// if (m68k_rtx_costs(XEXP(x, 1), mode, PLUS, 1, total, speed)) -// { -// if (REGNO_REG_CLASS(REGNO(XEXP(x, 0))) == ADDR_REGS) -// *total += 4; -// return true; -// } -// } return false; From ab8a4e993790f397307d8ec74581791e12470cf9 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Apr 2017 23:00:59 +0200 Subject: [PATCH 056/303] @B fix life analysis and commute_add_move, also some cleanup --- gcc/bbb-opts.c | 314 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 180 insertions(+), 134 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 7fd01139d0f3..48e2fa3fd255 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1,5 +1,6 @@ /* Bebbo's Optimizations. - Copyright (C) 2010-2016 Free Software Foundation, Inc. + Copyright (C) 2010-2017 Free Software Foundation, Inc. + Copyright (C) 2017 Stefan "Bebbo" Franke. This file is part of GCC. @@ -26,14 +27,7 @@ * check if a->b->a can be moved out of a loop. * * #2 strcpy_opt - * move a,reg - * move reg,b - * cmp #0,reg - * jcc - * - * -> - * move a,b - * jcc + * check if a temp reg can be eliminated. * */ @@ -55,39 +49,91 @@ #include /* enough for m68k. */ -typedef unsigned insn_info; //[(FIRST_PSEUDO_REGISTER + sizeof(unsigned) * 8 - 1) / (sizeof(unsigned) * 8)]; - -static inline void -resetii (unsigned & ii) +struct insn_info { - ii = 0; -} + unsigned mask; -static inline void -setii (unsigned regno, unsigned & ii) -{ - ii |= 1 << regno; -} + insn_info () : + mask (0) + { + } -static inline void -clearii (unsigned regno, unsigned & ii) -{ - ii &= ~(1 << regno); -} + inline void + reset () + { + mask = 0; + } -static inline bool -getii (unsigned regno, unsigned & ii) -{ - return ii & (1 << regno) ? true : false; -} + inline void + set (int regno) + { + mask |= 1 << regno; + } + + inline void + unset (int regno) + { + mask &= ~(1 << regno); + } + + inline bool + get (int regno) + { + return (mask & (1 << regno)) != 0; + } + + inline insn_info + operator | (insn_info const & o) const + { + insn_info t; + t.mask = mask | o.mask; + return t; + } + + inline insn_info + operator & (insn_info const & o) const + { + insn_info t; + t.mask = mask & o.mask; + return t; + } + + inline insn_info & + operator |= (insn_info const & o) + { + mask |= o.mask; + return *this; + } + + inline insn_info & + operator &= (insn_info const & o) + { + mask &= o.mask; + return *this; + } + + inline bool + operator == (insn_info const & o) + { + return mask == o.mask; + } + + inline insn_info + operator ~ () const + { + insn_info t; + t.mask = ~mask; + return t; + } +}; /* scan rtx for registers. */ static void -scanii (rtx x, unsigned & ii) +scanii (rtx x, insn_info & ii) { if (REG_P(x)) { - setii (REGNO(x), ii); + ii.set (REGNO(x)); return; } @@ -117,61 +163,27 @@ clear (void) infos.clear (); } -static void -dump_costs (void) -{ - rtx d0 = gen_raw_REG (SImode, 0); - rtx d0b = gen_raw_REG (QImode, 0); - rtx d1 = gen_raw_REG (SImode, 1); - rtx d1b = gen_raw_REG (QImode, 1); - rtx a0 = gen_raw_REG (SImode, 8); - rtx a1 = gen_raw_REG (SImode, 9); - - struct ICO - { - char const * name; - rtx set; - } data[] = - { - { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) }, - { "move a0,d0", gen_rtx_SET(d0, a0) }, - { "move (a0),d0", gen_rtx_SET(d0, gen_rtx_MEM (SImode, a0)) }, - { "move d0,(a0)", gen_rtx_SET(gen_rtx_MEM (SImode, a0), d0) }, - { "move d1,(a1)+", gen_rtx_SET(d1, gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode, a1))) }, - { "move (a0),(a1)", gen_rtx_SET(gen_rtx_MEM (SImode, a1), gen_rtx_MEM (SImode, a0)) }, - { 0, 0 } }, *p; - - for (p = data; p->name; ++p) - { - int cost = insn_rtx_cost (p->set, true); - fprintf (stderr, "%s: %d\n", p->name, cost); - } -} - - static void dump_insns (char const * name) { - rtx_insn *insn, *next; - fprintf(stderr, "====================================: %s\n", name); - for (unsigned i = 0; i < insns.size(); ++i) + fprintf (stderr, "====================================: %s\n", name); + for (unsigned i = 0; i < insns.size (); ++i) { insn_info & ii = infos[i]; for (int j = 0; j < 8; ++j) - if (getii(j, ii)) - fprintf(stderr, "d%d ", j); + if (ii.get (j)) + fprintf (stderr, "d%d ", j); for (int j = 8; j < 16; ++j) - if (getii(j, ii)) - fprintf(stderr, "a%d ", j-8); + if (ii.get (j)) + fprintf (stderr, "a%d ", j - 8); - fprintf(stderr, "\t"); - debug_rtx(insns[i]); + fprintf (stderr, "\t"); + debug_rtx (insns[i]); } } - /* * Create a filtered view of insns - keep only those to work with. */ @@ -192,7 +204,7 @@ filter_insns () { // debug_rtx (insn); if (JUMP_P(insn)) - jumps.push_back(insn); + jumps.push_back (insn); insn2index.insert (std::make_pair (insn, insns.size ())); insns.push_back (insn); @@ -201,13 +213,12 @@ filter_insns () /* prepare insn_info */ insn_info ii; - resetii (ii); for (unsigned i = 0; i < insns.size (); ++i) { infos.push_back (ii); } - /* own analyze life */ + /* own analyze reg life */ std::vector> todo; todo.push_back (std::make_pair (insns.size () - 1, ii)); @@ -236,53 +247,40 @@ filter_insns () if (JUMP_LABEL(*i) == insn) { std::map::iterator j = insn2index.find (*i); - if (j != insn2index.end()) + if (j != insn2index.end ()) todo.push_back (std::make_pair (j->second, ii)); } } continue; } - rtx set = single_set (insn); - if (set == 0) - { - if (JUMP_P(insn)) { - resetii(ii); - setii(0, ii); - infos[pos] = ii; - continue; - } - fprintf(stderr, "##### "); - debug_rtx(insn); - continue; - } - - rtx src = SET_SRC(set); - rtx dst = SET_DEST(set); - - debug_rtx(insn); + rtx pattern = PATTERN (insn); if (CALL_P(insn)) { /* a call sets d0 and kills d1,a0,a1. */ - if (getii (1, ii)) + if (ii.get (1)) fprintf (stderr, "d1 used after call\n"); - if (getii (8, ii)) + if (ii.get (8)) fprintf (stderr, "a0 used after call\n"); - if (getii (9, ii)) + if (ii.get (9)) fprintf (stderr, "a1 used after call\n"); - resetii (ii); + ii.unset(0); + ii.unset(1); + ii.unset(8); + ii.unset(9); + + // FIXME: get the DECL and read attributes. // use regs depending on flag mregparm for (int i = 0; i < amigaos_regparm; ++i) { - setii (i, ii); - setii (i + 8, ii); + ii.set (i); + ii.set (i + 8); } // check for reg use - if (REG_P(src)) - setii (REGNO(src), ii); + scanii (pattern, ii); infos[pos] = ii; continue; @@ -290,37 +288,55 @@ filter_insns () if (JUMP_P(insn)) { - if (ANY_RETURN_P(src)) + if (ANY_RETURN_P(pattern)) { - resetii (ii); - setii (0, ii); + ii.reset (); + ii.set (0); } else { ii |= infos[pos]; // check for reg use - if (REG_P(src)) - setii (REGNO(src), ii); + scanii(PATTERN(insn), ii); + + } + infos[pos] = ii; + continue; + } + + rtx set = single_set (insn); + if (set == 0) + { + if (GET_CODE (pattern) == USE) + { + rtx x = XEXP(pattern, 0); + if (REG_P(x)) + ii.set(REGNO(x)); + infos[pos] = ii; + continue; } + + fprintf (stderr, "##### "); + debug_rtx (insn); + scanii (pattern, ii); infos[pos] = ii; continue; } + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); // scan insn for regs // a def stop propagation // a use starts propagation // also add use to current ii insn_info use; - resetii (use); - insn_info def; - resetii (def); scanii (src, use); if (REG_P(dst)) - setii (REGNO(dst), def); + def.set (REGNO(dst)); else scanii (dst, use); @@ -808,16 +824,16 @@ commute_add_move (void) if (!set) continue; - rtx reg1 = SET_DEST(set); - if (!REG_P(reg1)) + rtx reg1dst = SET_DEST(set); + if (!REG_P(reg1dst)) continue; rtx plus = SET_SRC(set); if (GET_CODE(plus) != PLUS) continue; - rtx reg2 = XEXP(plus, 0); - if (!REG_P(reg2)) + rtx reg1src = XEXP(plus, 0); + if (!REG_P(reg1src) || reg1src == reg1dst) continue; rtx cnst = XEXP(plus, 1); @@ -834,35 +850,35 @@ commute_add_move (void) continue; rtx memreg = XEXP(dst, 0); - if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg2)) + if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src)) continue; int oldcost1 = insn_rtx_cost (set, true); int oldcost2 = insn_rtx_cost (set2, true); - fprintf (stderr, "commute_add_move found, oldcost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2); + fprintf (stderr, "commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2); - //debug_rtx (insn); - //debug_rtx (next); + debug_rtx (insn); + debug_rtx (next); - rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1); + rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst); rtx newmem = replace_equiv_address_nv (dst, pinc); if (validate_change (next, &SET_DEST(set2), newmem, 0)) { SET_INSN_DELETED(insn); - insn = emit_insn_before (gen_movsi (reg1, reg2), next); + insn = emit_insn_before (gen_movsi (reg1dst, reg1src), next); - add_reg_note (next, REG_INC, reg1); + add_reg_note (next, REG_INC, reg1dst); int newcost1 = insn_rtx_cost (set, true); int newcost2 = insn_rtx_cost (set2, true); - fprintf (stderr, "commute_add_move found, newcost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2); + fprintf (stderr, "commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2); - //debug_rtx (insn); - //debug_rtx (next); + debug_rtx (insn); + debug_rtx (next); df_insn_rescan (insn); df_insn_rescan (next); @@ -889,13 +905,43 @@ const_cmp_to_sub (void) if (dst != cc0_rtx) continue; - fprintf (stderr, "cc0:"); - debug_rtx (insn); +// fprintf (stderr, "cc0:"); +// debug_rtx (insn); } #endif return change_count; } +static unsigned +elim_dead_assign (void) +{ + unsigned change_count = 0; + for (unsigned index = 0; index + 1 < insns.size (); ++index) + { + rtx_insn * insn = insns[index]; + if (!NONJUMP_INSN_P(insn)) + continue; + + rtx set = single_set (insn); + if (!set) + continue; + + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); + if (!REG_P(dst) || !REG_P(src)) + continue; + + if (!infos[index].get (REGNO(dst))) + { + fprintf (stderr, "eliminate dead assignment to %d:", REGNO(dst)); + debug_rtx (insn); + SET_INSN_DELETED(insn); + ++change_count; + } + } + return change_count; +} + /* Main entry point to the pass. */ static unsigned int execute_bbb_optimizations (void) @@ -904,7 +950,6 @@ execute_bbb_optimizations (void) df_note_add_problem (); df_analyze (); -// dump_insns ("bbb 0"); filter_insns (); for (;;) @@ -925,15 +970,16 @@ execute_bbb_optimizations (void) if (const_cmp_to_sub ()) done = 0, filter_insns (); + if (elim_dead_assign ()) + done = 0, filter_insns (); + if (done) break; } - dump_insns ("bbb 1"); +// dump_insns ("bbb 1"); clear (); - dump_costs (); - return 0; } @@ -964,7 +1010,7 @@ namespace virtual bool gate (function *) { - return TARGET_AMIGA; + return TARGET_AMIGA && flag_bbb_opts; } virtual unsigned int From f5cd54a27e20a9ef7b1ec441fad9486216a87253 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 6 Apr 2017 13:41:46 +0200 Subject: [PATCH 057/303] @N const_cmp_to_sub --- gcc/bbb-opts.c | 187 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 146 insertions(+), 41 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 48e2fa3fd255..44616bcabd6b 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -48,7 +48,9 @@ #include #include -/* enough for m68k. */ +/* Enough for m68k. + * Why a class? Maybe extend it for general usage. + */ struct insn_info { unsigned mask; @@ -127,7 +129,7 @@ struct insn_info } }; -/* scan rtx for registers. */ +/* scan rtx for registers and set the corresponding flags. */ static void scanii (rtx x, insn_info & ii) { @@ -149,11 +151,17 @@ scanii (rtx x, insn_info & ii) } } +/* + * Collect some data. + */ static std::vector insns; static std::vector jumps; static std::map insn2index; static std::vector infos; +/* + * Reset collected data. + */ static void clear (void) { @@ -163,6 +171,10 @@ clear (void) infos.clear (); } +/* + * Helper function to dump the code. + * Sometimes used during debugging. + */ static void dump_insns (char const * name) { @@ -188,7 +200,7 @@ dump_insns (char const * name) * Create a filtered view of insns - keep only those to work with. */ static void -filter_insns () +update_meta_data () { rtx_insn *insn, *next; clear (); @@ -258,18 +270,11 @@ filter_insns () if (CALL_P(insn)) { - /* a call sets d0 and kills d1,a0,a1. */ - if (ii.get (1)) - fprintf (stderr, "d1 used after call\n"); - if (ii.get (8)) - fprintf (stderr, "a0 used after call\n"); - if (ii.get (9)) - fprintf (stderr, "a1 used after call\n"); - - ii.unset(0); - ii.unset(1); - ii.unset(8); - ii.unset(9); + /* a call sets d0 and maybe also d1,a0,a1. */ + ii.unset (0); + ii.unset (1); + ii.unset (8); + ii.unset (9); // FIXME: get the DECL and read attributes. // use regs depending on flag mregparm @@ -298,14 +303,13 @@ filter_insns () ii |= infos[pos]; // check for reg use - scanii(PATTERN(insn), ii); + scanii (PATTERN (insn), ii); } infos[pos] = ii; continue; } - rtx set = single_set (insn); if (set == 0) { @@ -313,13 +317,16 @@ filter_insns () { rtx x = XEXP(pattern, 0); if (REG_P(x)) - ii.set(REGNO(x)); + ii.set (REGNO(x)); infos[pos] = ii; continue; } - fprintf (stderr, "##### "); - debug_rtx (insn); + if (GET_CODE (pattern) != PARALLEL) + { + fprintf (stderr, "##### "); + debug_rtx (insn); + } scanii (pattern, ii); infos[pos] = ii; continue; @@ -501,7 +508,7 @@ propagate_moves () { std::vector::iterator label_iter = jump_out.begin (); int fixup = 0; - fprintf (stderr, "need %d jump out fixups\n", jump_out.size ()); + fprintf (stderr, ": need %d jump out fixups\n", jump_out.size ()); for (unsigned k = *i + 1; k != *j; ++k) { @@ -574,7 +581,7 @@ propagate_moves () rtx_insn * after = insns[index + 1]; rtx bset = single_set (before); - fprintf (stderr, "condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti)); + fprintf (stderr, ": condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti)); /* Move in front of loop and mark as dead. */ remove_insn (ii); @@ -607,7 +614,7 @@ propagate_moves () /* add fixes if there were jumps out of the loop. */ if (jump_out.size ()) { - fprintf (stderr, "fixing %d jump outs\n", jump_out.size ()); + fprintf (stderr, ": fixing %d jump outs\n", jump_out.size ()); for (unsigned k = 0; k < jump_out.size (); ++k) { @@ -698,7 +705,7 @@ opt_strcpy () fprintf ( stderr, - "condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst)); + ": condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst)); for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1)) if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) @@ -856,7 +863,7 @@ commute_add_move (void) int oldcost1 = insn_rtx_cost (set, true); int oldcost2 = insn_rtx_cost (set2, true); - fprintf (stderr, "commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2); + fprintf (stderr, ": commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2); debug_rtx (insn); debug_rtx (next); @@ -875,7 +882,7 @@ commute_add_move (void) int newcost1 = insn_rtx_cost (set, true); int newcost2 = insn_rtx_cost (set2, true); - fprintf (stderr, "commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2); + fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2); debug_rtx (insn); debug_rtx (next); @@ -889,24 +896,122 @@ commute_add_move (void) return change_count; } +/* + * Replace + * + * move x,dx + * cmp dx,dy + * + * if dx and dy are both dead after compare. + * + * with + * + * sub #n,dx + * + d0 d1 d2 a0 a1 a7 (insn 99 59 41 7 (set (reg:SI 2 d2) + (const_int 1 [0x1])) sn.c:8 38 {*movsi_m68k} + (nil)) + d0 d1 d2 a0 a1 a7 (insn 41 99 42 7 (set (cc0) + (compare (reg/v:SI 1 d1 [orig:54 n ] [54]) + (reg:SI 2 d2))) sn.c:8 16 {*m68k.md:499} + (expr_list:REG_DEAD (reg:SI 2 d2) + (expr_list:REG_DEAD (reg/v:SI 1 d1 [orig:54 n ] [54]) + (nil)))) + * + */ static unsigned const_cmp_to_sub (void) { unsigned change_count = 0; #if HAVE_cc0 - for (unsigned index = 0; index + 1 < insns.size (); ++index) + for (unsigned index = 1; index + 1 < insns.size (); ++index) { rtx_insn * insn = insns[index]; - rtx set = single_set (insn); - if (!set) + rtx seti = single_set (insn); + if (!seti) continue; - rtx dst = SET_DEST(set); - if (dst != cc0_rtx) + rtx dsti = SET_DEST(seti); + if (dsti != cc0_rtx) + continue; + + rtx srci = SET_SRC(seti); + if (GET_CODE(srci) != COMPARE) + continue; + + rtx left = XEXP(srci, 0); + rtx right = XEXP(srci, 1); + if (!REG_P(left) || !REG_P(right)) continue; -// fprintf (stderr, "cc0:"); -// debug_rtx (insn); + if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) + continue; + + fprintf (stderr, ": found reg-reg compare with both dead\n"); + + // maybe add a search? + rtx_insn * prev = insns[index - 1]; + rtx setp = single_set (prev); + if (!setp) + continue; + + rtx dstp = SET_DEST(setp); + if (!REG_P(dstp) || dstp != left) + continue; + + rtx srcp = SET_SRC(setp); + if (!CONST_INT_P(srcp)) + continue; + + int intval = -INTVAL(srcp); + if (intval < -8 || intval > 7) + continue; + + enum machine_mode mode = GET_MODE(dstp); + rtx reg = dstp == left ? right : left; + rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT(mode, intval)); + + SET_SRC(setp) = plus; + SET_DEST(setp) = reg; + + int num_clobbers_to_add = 0; + int insn_code_number = recog (PATTERN (prev), prev, &num_clobbers_to_add); + + SET_SRC(setp) = srcp; + SET_DEST(setp) = dstp; + + if (insn_code_number < 0) + continue; + + debug_rtx(prev); + debug_rtx(insn); + + // also convert current statement to cmp #0, reg + SET_INSN_DELETED(insn); + rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0))); + insn = emit_insn_after(neu, prev); + add_reg_note (insn, REG_DEAD, reg); + + SET_INSN_DELETED(prev); + neu = gen_rtx_SET(reg, plus); + prev = emit_insn_before(neu, insn); + + int omitted_regno = REGNO(dstp == left ? left: right); + if (!(df->hard_regs_live_count[omitted_regno] -= 2)) + df_set_regs_ever_live (omitted_regno, false); + + fprintf (stderr, ": replaced reg-reg compare with sub\n"); + debug_rtx(prev); + debug_rtx(insn); + + if (dstp != left) + { + // invert all conditions using this statement. + + } + + + ++change_count; } #endif return change_count; @@ -933,7 +1038,7 @@ elim_dead_assign (void) if (!infos[index].get (REGNO(dst))) { - fprintf (stderr, "eliminate dead assignment to %d:", REGNO(dst)); + fprintf (stderr, ": eliminate dead assignment to %d:", REGNO(dst)); debug_rtx (insn); SET_INSN_DELETED(insn); ++change_count; @@ -950,28 +1055,28 @@ execute_bbb_optimizations (void) df_note_add_problem (); df_analyze (); - filter_insns (); + update_meta_data (); for (;;) { int done = 1; if (propagate_moves ()) - done = 0, filter_insns (); + done = 0, update_meta_data (); if (offset_2_autoinc ()) - done = 0, filter_insns (); + done = 0, update_meta_data (); if (opt_strcpy ()) - done = 0, filter_insns (); + done = 0, update_meta_data (); if (commute_add_move ()) - done = 0, filter_insns (); + done = 0, update_meta_data (); if (const_cmp_to_sub ()) - done = 0, filter_insns (); + done = 0, update_meta_data (); if (elim_dead_assign ()) - done = 0, filter_insns (); + done = 0, update_meta_data (); if (done) break; From 485cc891b48af316e84f77e6142a0c28b80c596d Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 6 Apr 2017 22:05:20 +0200 Subject: [PATCH 058/303] @N const_cmp_to_sub seems working --- gcc/bbb-opts.c | 249 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 192 insertions(+), 57 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 44616bcabd6b..8a98fbfaad7c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -50,45 +50,64 @@ /* Enough for m68k. * Why a class? Maybe extend it for general usage. + * + * Track use & def separate to determine starting points. */ struct insn_info { - unsigned mask; + unsigned _use; + unsigned _def; insn_info () : - mask (0) + _use (0), _def (0) { } inline void reset () { - mask = 0; + _use = 0; + _def = 0; } inline void - set (int regno) + use (int regno) { - mask |= 1 << regno; + _use |= 1 << regno; + } + + inline void + def (int regno) + { + _use |= 1 << regno; + _def |= 1 << regno; } inline void unset (int regno) { - mask &= ~(1 << regno); + _use &= ~(1 << regno); + _def &= ~(1 << regno); } inline bool - get (int regno) + is_use (int regno) { - return (mask & (1 << regno)) != 0; + return (_use & (1 << regno)) != 0; + } + + inline bool + is_def (int regno) + { + return (_def & (1 << regno)) != 0; } inline insn_info operator | (insn_info const & o) const { insn_info t; - t.mask = mask | o.mask; + t._use = _use | o._use; + t._def = _def | o._def; return t; } @@ -96,46 +115,67 @@ struct insn_info operator & (insn_info const & o) const { insn_info t; - t.mask = mask & o.mask; + t._use = _use & o._use; + t._def = _def & o._def; return t; } inline insn_info & operator |= (insn_info const & o) { - mask |= o.mask; + _use |= o._use; + _def |= o._def; return *this; } inline insn_info & operator &= (insn_info const & o) { - mask &= o.mask; + _use &= o._use; + _def &= o._def; return *this; } inline bool operator == (insn_info const & o) { - return mask == o.mask; + return _use == o._use; } inline insn_info operator ~ () const { insn_info t; - t.mask = ~mask; + t._use = ~_use; + t._def = ~_def; return t; } + + inline bool contains(insn_info const & o) const { + if (o._def & ~_def) + return false; + if (o._use & ~_use) + return false; + return true; + } + + void + scan (rtx); }; /* scan rtx for registers and set the corresponding flags. */ -static void -scanii (rtx x, insn_info & ii) +void +insn_info::scan (rtx x) { if (REG_P(x)) { - ii.set (REGNO(x)); + use (REGNO(x)); + return; + } + + if (x == cc0_rtx) + { + use (FIRST_PSEUDO_REGISTER); return; } @@ -144,10 +184,10 @@ scanii (rtx x, insn_info & ii) for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - scanii (XEXP(x, i), ii); + scan (XEXP(x, i)); else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - scanii (XVECEXP(x, i, j), ii); + scan (XVECEXP(x, i, j)); } } @@ -171,6 +211,23 @@ clear (void) infos.clear (); } +static bool is_reg_dead(unsigned regno, unsigned pos) +{ + if (pos >= infos.size()) + return true; + + insn_info & ii0 = infos[pos++]; + if (!ii0.is_use(regno)) + return true; + + if (pos >= infos.size()) + return true; + + insn_info & ii1 = infos[pos]; + + return !ii1.is_use(regno); +} + /* * Helper function to dump the code. * Sometimes used during debugging. @@ -184,12 +241,15 @@ dump_insns (char const * name) insn_info & ii = infos[i]; for (int j = 0; j < 8; ++j) - if (ii.get (j)) - fprintf (stderr, "d%d ", j); + if (ii.is_use (j)) + fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j); for (int j = 8; j < 16; ++j) - if (ii.get (j)) - fprintf (stderr, "a%d ", j - 8); + if (ii.is_use (j)) + fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8); + + if (ii.is_use (FIRST_PSEUDO_REGISTER)) + fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); fprintf (stderr, "\t"); debug_rtx (insns[i]); @@ -246,7 +306,7 @@ update_meta_data () { rtx_insn * insn = insns[pos]; - if (pass && ii == infos[pos]) + if (pass && infos[pos].contains(ii)) break; ii |= infos[pos]; @@ -276,16 +336,16 @@ update_meta_data () ii.unset (8); ii.unset (9); - // FIXME: get the DECL and read attributes. + // FIXME: isuse the DECL and read attributes. // use regs depending on flag mregparm for (int i = 0; i < amigaos_regparm; ++i) { - ii.set (i); - ii.set (i + 8); + ii.use (i); + ii.use (i + 8); } // check for reg use - scanii (pattern, ii); + ii.scan (pattern); infos[pos] = ii; continue; @@ -296,14 +356,14 @@ update_meta_data () if (ANY_RETURN_P(pattern)) { ii.reset (); - ii.set (0); + ii.use (0); } else { ii |= infos[pos]; // check for reg use - scanii (PATTERN (insn), ii); + ii.scan (PATTERN (insn)); } infos[pos] = ii; @@ -317,7 +377,7 @@ update_meta_data () { rtx x = XEXP(pattern, 0); if (REG_P(x)) - ii.set (REGNO(x)); + ii.use (REGNO(x)); infos[pos] = ii; continue; } @@ -327,7 +387,7 @@ update_meta_data () fprintf (stderr, "##### "); debug_rtx (insn); } - scanii (pattern, ii); + ii.scan (pattern); infos[pos] = ii; continue; } @@ -341,13 +401,23 @@ update_meta_data () insn_info use; insn_info def; - scanii (src, use); + use.scan (src); if (REG_P(dst)) - def.set (REGNO(dst)); + def.def (REGNO(dst)); + else if (dst == cc0_rtx) + def.def (FIRST_PSEUDO_REGISTER); else - scanii (dst, use); + use.scan (dst); - infos[pos] = use | ii; + if (dst != cc0_rtx) + { + CC_STATUS_INIT; + NOTICE_UPDATE_CC(PATTERN (insn), insn); + if (cc_status.value1 || cc_status.value2) + def.def (FIRST_PSEUDO_REGISTER); + } + + infos[pos] = def | use | ii; ii &= ~def; ii |= use; @@ -778,15 +848,15 @@ offset_2_autoinc (void) if (!NONJUMP_INSN_P(insn)) continue; - rtx set = single_set (insn); - if (!set) + rtx use = single_set (insn); + if (!use) continue; - rtx reg = SET_DEST(set); + rtx reg = SET_DEST(use); if (!REG_P(reg)) continue; - rtx val = SET_SRC(set); + rtx val = SET_SRC(use); // fprintf(stderr, "possible start for offset_2_autoinc\n"); // //debug_rtx(insn); @@ -882,7 +952,8 @@ commute_add_move (void) int newcost1 = insn_rtx_cost (set, true); int newcost2 = insn_rtx_cost (set2, true); - fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, newcost2); + fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, + newcost2); debug_rtx (insn); debug_rtx (next); @@ -944,10 +1015,14 @@ const_cmp_to_sub (void) if (!REG_P(left) || !REG_P(right)) continue; - if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) - continue; +// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) +// continue; - fprintf (stderr, ": found reg-reg compare with both dead\n"); + if (!is_reg_dead(REGNO(left), index) || !is_reg_dead(REGNO(right), index)) + continue; + + fprintf (stderr, ": found reg-reg compare with both dead: %d %d\n", + is_reg_dead(REGNO(left), index), is_reg_dead(REGNO(right), index)); // maybe add a search? rtx_insn * prev = insns[index - 1]; @@ -956,7 +1031,7 @@ const_cmp_to_sub (void) continue; rtx dstp = SET_DEST(setp); - if (!REG_P(dstp) || dstp != left) + if (!REG_P(dstp)) continue; rtx srcp = SET_SRC(setp); @@ -969,7 +1044,7 @@ const_cmp_to_sub (void) enum machine_mode mode = GET_MODE(dstp); rtx reg = dstp == left ? right : left; - rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT(mode, intval)); + rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT (mode, intval)); SET_SRC(setp) = plus; SET_DEST(setp) = reg; @@ -983,33 +1058,93 @@ const_cmp_to_sub (void) if (insn_code_number < 0) continue; - debug_rtx(prev); - debug_rtx(insn); + debug_rtx (prev); + debug_rtx (insn); // also convert current statement to cmp #0, reg SET_INSN_DELETED(insn); rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0))); - insn = emit_insn_after(neu, prev); + insn = emit_insn_after (neu, prev); add_reg_note (insn, REG_DEAD, reg); SET_INSN_DELETED(prev); neu = gen_rtx_SET(reg, plus); - prev = emit_insn_before(neu, insn); + prev = emit_insn_before (neu, insn); - int omitted_regno = REGNO(dstp == left ? left: right); - if (!(df->hard_regs_live_count[omitted_regno] -= 2)) - df_set_regs_ever_live (omitted_regno, false); +// urks - unknown side effects +// int omitted_regno = REGNO(dstp); +// if (!(df->hard_regs_live_count[omitted_regno] -= 2)) +// df_set_regs_ever_live (omitted_regno, false); fprintf (stderr, ": replaced reg-reg compare with sub\n"); - debug_rtx(prev); - debug_rtx(insn); + debug_rtx (prev); + debug_rtx (insn); if (dstp != left) { // invert all conditions using this statement. + std::vector todo; + std::vector done; + done.resize(insns.size()); + todo.push_back (index + 1); - } + while (todo.size ()) + { + unsigned pos = todo[todo.size () - 1]; + todo.pop_back (); + + if (done[pos]) + continue; + done[pos] = 1; + + if (infos[pos].is_def (FIRST_PSEUDO_REGISTER)) + continue; + + if (pos + 1 < infos.size ()) + todo.push_back (pos + 1); + + rtx_insn * patchme = insns[pos]; + if (!JUMP_P(insn)) + continue; + + std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme)); + if (j != insn2index.end ()) + todo.push_back (j->second); + + rtx jmppattern = PATTERN (patchme); + + rtx jmpsrc = XEXP(jmppattern, 1); + if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + { + rtx condition = XEXP(jmpsrc, 0); + RTX_CODE code = GET_CODE(condition); + RTX_CODE newcode = code; + if (code == GE) + newcode = LE; + else if (code == GT) + newcode = LT; + else if (code == LT) + newcode = GT; + else if (code == LE) + newcode = GE; + else if (code == GEU) + newcode = LEU; + else if (code == GTU) + newcode = LTU; + else if (code == LTU) + newcode = GTU; + else if (code == LEU) + newcode = GEU; + + if (code != newcode) + { + fprintf (stderr, ": patch jcc %d -> %d\n", code, newcode); + XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1)); + } + } + } + } ++change_count; } @@ -1036,7 +1171,7 @@ elim_dead_assign (void) if (!REG_P(dst) || !REG_P(src)) continue; - if (!infos[index].get (REGNO(dst))) + if (!infos[index].is_use (REGNO(dst))) { fprintf (stderr, ": eliminate dead assignment to %d:", REGNO(dst)); debug_rtx (insn); From 9967eed30e2e8f28bb48aa5a39d1cd578d4e0a7a Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 7 Apr 2017 04:03:53 +0200 Subject: [PATCH 059/303] @B avoid illegal insns --- gcc/bbb-opts.c | 188 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 132 insertions(+), 56 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 8a98fbfaad7c..d9e77c53856d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -79,7 +79,6 @@ struct insn_info inline void def (int regno) { - _use |= 1 << regno; _def |= 1 << regno; } @@ -151,7 +150,9 @@ struct insn_info return t; } - inline bool contains(insn_info const & o) const { + inline bool + contains (insn_info const & o) const + { if (o._def & ~_def) return false; if (o._use & ~_use) @@ -211,21 +212,22 @@ clear (void) infos.clear (); } -static bool is_reg_dead(unsigned regno, unsigned pos) +static bool +is_reg_dead (unsigned regno, unsigned pos) { - if (pos >= infos.size()) + if (pos >= infos.size ()) return true; insn_info & ii0 = infos[pos++]; - if (!ii0.is_use(regno)) + if (!ii0.is_use (regno)) return true; - if (pos >= infos.size()) + if (pos >= infos.size ()) return true; insn_info & ii1 = infos[pos]; - return !ii1.is_use(regno); + return !ii1.is_use (regno); } /* @@ -274,7 +276,6 @@ update_meta_data () if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn)) { - // debug_rtx (insn); if (JUMP_P(insn)) jumps.push_back (insn); @@ -306,7 +307,7 @@ update_meta_data () { rtx_insn * insn = insns[pos]; - if (pass && infos[pos].contains(ii)) + if (pass && infos[pos].contains (ii)) break; ii |= infos[pos]; @@ -578,7 +579,6 @@ propagate_moves () { std::vector::iterator label_iter = jump_out.begin (); int fixup = 0; - fprintf (stderr, ": need %d jump out fixups\n", jump_out.size ()); for (unsigned k = *i + 1; k != *j; ++k) { @@ -651,7 +651,8 @@ propagate_moves () rtx_insn * after = insns[index + 1]; rtx bset = single_set (before); - fprintf (stderr, ": condition met, moving regs %d, %d\n", REGNO(srci), REGNO(dsti)); + fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %d, %d\n", + REGNO(srci), REGNO(dsti)); /* Move in front of loop and mark as dead. */ remove_insn (ii); @@ -684,7 +685,7 @@ propagate_moves () /* add fixes if there were jumps out of the loop. */ if (jump_out.size ()) { - fprintf (stderr, ": fixing %d jump outs\n", jump_out.size ()); + fprintf (stderr, ":bbb: propagate_moves fixing %d jump outs\n", jump_out.size ()); for (unsigned k = 0; k < jump_out.size (); ++k) { @@ -763,7 +764,7 @@ opt_strcpy () SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); insn_code_number = recog (PATTERN (reg2x), reg2x, &num_clobbers_to_add); - if (insn_code_number < 0) + if (insn_code_number < 0 || !check_asm_operands (reg2x)) { /* restore register. */ SET_SRC(single_set(reg2x)) = SET_DEST(single_set (x2reg)); @@ -775,7 +776,8 @@ opt_strcpy () fprintf ( stderr, - ": condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst)); + ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %d\n", + REGNO(dst)); for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1)) if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) @@ -930,14 +932,6 @@ commute_add_move (void) if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src)) continue; - int oldcost1 = insn_rtx_cost (set, true); - int oldcost2 = insn_rtx_cost (set2, true); - - fprintf (stderr, ": commute_add_move found, old cost: %d = %d + %d\n", oldcost1 + oldcost2, oldcost1, oldcost2); - - debug_rtx (insn); - debug_rtx (next); - rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst); rtx newmem = replace_equiv_address_nv (dst, pinc); @@ -949,14 +943,7 @@ commute_add_move (void) add_reg_note (next, REG_INC, reg1dst); - int newcost1 = insn_rtx_cost (set, true); - int newcost2 = insn_rtx_cost (set2, true); - - fprintf (stderr, ": commute_add_move found, new cost: %d = %d + %d\n", newcost1 + newcost2, newcost1, - newcost2); - - debug_rtx (insn); - debug_rtx (next); + fprintf (stderr, ":bbb: commute_add_move found\n"); df_insn_rescan (insn); df_insn_rescan (next); @@ -1018,11 +1005,15 @@ const_cmp_to_sub (void) // if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) // continue; - if (!is_reg_dead(REGNO(left), index) || !is_reg_dead(REGNO(right), index)) - continue; + // TODO + // FEATURE: check if the next uses are also a add/sub + // then maybe that add/sub can be adjusted too - fprintf (stderr, ": found reg-reg compare with both dead: %d %d\n", - is_reg_dead(REGNO(left), index), is_reg_dead(REGNO(right), index)); + if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index)) + continue; + + fprintf (stderr, ":bbb: found reg-reg compare with both dead: %d %d\n", is_reg_dead (REGNO(left), index), + is_reg_dead (REGNO(right), index)); // maybe add a search? rtx_insn * prev = insns[index - 1]; @@ -1051,6 +1042,8 @@ const_cmp_to_sub (void) int num_clobbers_to_add = 0; int insn_code_number = recog (PATTERN (prev), prev, &num_clobbers_to_add); + if (insn_code_number >= 0 && !check_asm_operands (prev)) + insn_code_number = -1; SET_SRC(setp) = srcp; SET_DEST(setp) = dstp; @@ -1058,9 +1051,6 @@ const_cmp_to_sub (void) if (insn_code_number < 0) continue; - debug_rtx (prev); - debug_rtx (insn); - // also convert current statement to cmp #0, reg SET_INSN_DELETED(insn); rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0))); @@ -1076,16 +1066,14 @@ const_cmp_to_sub (void) // if (!(df->hard_regs_live_count[omitted_regno] -= 2)) // df_set_regs_ever_live (omitted_regno, false); - fprintf (stderr, ": replaced reg-reg compare with sub\n"); - debug_rtx (prev); - debug_rtx (insn); + fprintf (stderr, ":bbb: const_cmp_to_sub replaced reg-reg compare with sub\n"); if (dstp != left) { // invert all conditions using this statement. std::vector todo; std::vector done; - done.resize(insns.size()); + done.resize (insns.size ()); todo.push_back (index + 1); while (todo.size ()) @@ -1139,7 +1127,7 @@ const_cmp_to_sub (void) if (code != newcode) { - fprintf (stderr, ": patch jcc %d -> %d\n", code, newcode); + fprintf (stderr, ":bbb: patch jcc %d -> %d\n", code, newcode); XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1)); } } @@ -1173,8 +1161,7 @@ elim_dead_assign (void) if (!infos[index].is_use (REGNO(dst))) { - fprintf (stderr, ": eliminate dead assignment to %d:", REGNO(dst)); - debug_rtx (insn); + fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst)); SET_INSN_DELETED(insn); ++change_count; } @@ -1182,6 +1169,86 @@ elim_dead_assign (void) return change_count; } +/* + * rare and only little gain - but :-) + lea (-1,a0),a1 + add.l d1,a1 + subq.l #1,d1 + -> + move.l a0,a1 + subq.l #1,d1 + add.l d1,a1 + */ +static unsigned +merge_add (void) +{ + unsigned change_count = 0; + for (unsigned index = 0; index + 2 < insns.size (); ++index) + { + rtx_insn * ins1 = insns[index]; + rtx_insn * ins2 = insns[index + 1]; + rtx_insn * ins3 = insns[index + 2]; + if (!NONJUMP_INSN_P(ins1) && !NONJUMP_INSN_P(ins2) && !NONJUMP_INSN_P(ins3)) + continue; + + rtx set1 = single_set (ins1); + rtx set2 = single_set (ins2); + rtx set3 = single_set (ins3); + if (!set1 || !set2 || !set3) + continue; + + rtx dst1 = SET_DEST(set1); + rtx dst2 = SET_DEST(set2); + rtx dst3 = SET_DEST(set3); + if (!REG_P(dst1) || !REG_P(dst2) || !REG_P(dst3)) + continue; + + CC_STATUS_INIT; + NOTICE_UPDATE_CC(PATTERN (ins2), ins2); + if (cc_status.value1 || cc_status.value2) + continue; + + rtx src1 = SET_SRC(set1); + rtx src2 = SET_SRC(set2); + rtx src3 = SET_SRC(set3); + if (GET_CODE(src1) != PLUS || GET_CODE(src2) != PLUS || GET_CODE(src3) != PLUS) + continue; + + rtx l1 = XEXP(src1, 0); + rtx l2 = XEXP(src2, 0); + rtx l3 = XEXP(src3, 0); + + rtx r1 = XEXP(src1, 1); + rtx r2 = XEXP(src2, 1); + rtx r3 = XEXP(src3, 1); + if (!CONST_INT_P(r1) || !REG_P(r2) || !CONST_INT_P(r3)) + continue; + + if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3)) + continue; + + fprintf (stderr, ": merge_add pattern found\n"); + + SET_SRC(set1) = l1; + remove_insn (ins2); + add_insn_after (ins2, ins3, 0); + } + return change_count; +} + +/* + * Always prefer lower register numbers within the class. + */ +static unsigned +bb_reg_rename(void) +{ + unsigned change_count = 0; + for (unsigned index = 0; index < insns.size (); ++index) + { + } + return change_count; +} + /* Main entry point to the pass. */ static unsigned int execute_bbb_optimizations (void) @@ -1195,22 +1262,31 @@ execute_bbb_optimizations (void) for (;;) { int done = 1; - if (propagate_moves ()) - done = 0, update_meta_data (); + for (;;) + { + if (propagate_moves ()) + done = 0, update_meta_data (); - if (offset_2_autoinc ()) - done = 0, update_meta_data (); + if (offset_2_autoinc ()) + done = 0, update_meta_data (); - if (opt_strcpy ()) - done = 0, update_meta_data (); + if (opt_strcpy ()) + done = 0, update_meta_data (); - if (commute_add_move ()) - done = 0, update_meta_data (); + if (commute_add_move ()) + done = 0, update_meta_data (); - if (const_cmp_to_sub ()) - done = 0, update_meta_data (); + if (const_cmp_to_sub ()) + done = 0, update_meta_data (); + + if (merge_add ()) + done = 0, update_meta_data (); + + if (elim_dead_assign ()) + done = 0, update_meta_data (); + } - if (elim_dead_assign ()) + if (bb_reg_rename ()) done = 0, update_meta_data (); if (done) @@ -1250,7 +1326,7 @@ namespace virtual bool gate (function *) { - return TARGET_AMIGA && flag_bbb_opts; + return TARGET_AMIGA;// && flag_bbb_opts; } virtual unsigned int From 7ea53a15d0e3f77f38f9383d8779c7755c499e4b Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 7 Apr 2017 04:07:36 +0200 Subject: [PATCH 060/303] @B fix loop hang --- gcc/bbb-opts.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index d9e77c53856d..c525ae432071 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1240,7 +1240,7 @@ merge_add (void) * Always prefer lower register numbers within the class. */ static unsigned -bb_reg_rename(void) +bb_reg_rename (void) { unsigned change_count = 0; for (unsigned index = 0; index < insns.size (); ++index) @@ -1262,29 +1262,26 @@ execute_bbb_optimizations (void) for (;;) { int done = 1; - for (;;) - { - if (propagate_moves ()) - done = 0, update_meta_data (); + if (propagate_moves ()) + done = 0, update_meta_data (); - if (offset_2_autoinc ()) - done = 0, update_meta_data (); + if (offset_2_autoinc ()) + done = 0, update_meta_data (); - if (opt_strcpy ()) - done = 0, update_meta_data (); + if (opt_strcpy ()) + done = 0, update_meta_data (); - if (commute_add_move ()) - done = 0, update_meta_data (); + if (commute_add_move ()) + done = 0, update_meta_data (); - if (const_cmp_to_sub ()) - done = 0, update_meta_data (); + if (const_cmp_to_sub ()) + done = 0, update_meta_data (); - if (merge_add ()) - done = 0, update_meta_data (); + if (merge_add ()) + done = 0, update_meta_data (); - if (elim_dead_assign ()) - done = 0, update_meta_data (); - } + if (elim_dead_assign ()) + done = 0, update_meta_data (); if (bb_reg_rename ()) done = 0, update_meta_data (); @@ -1326,7 +1323,7 @@ namespace virtual bool gate (function *) { - return TARGET_AMIGA;// && flag_bbb_opts; + return TARGET_AMIGA; // && flag_bbb_opts; } virtual unsigned int From cf6a128caf791e74460c8f312e624be2ab373b4e Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 8 Apr 2017 17:06:18 +0200 Subject: [PATCH 061/303] @N add option letters to -fbbb --- gcc/config/m68k/amigaos.opt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 2d8bed0a9103..a5a14449dea9 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -43,6 +43,6 @@ mcrt= Target RejectNegative Var(amigaos_crt) Joined Specify startup binary -fbbb -Target Var(flag_bbb_opts,1) UInteger Init(0) +fbbb= +Target Var(flag_bbb_opts) Joined Enable Bebbo's optimizations From 477bce8c47781fce8d11797829a3bd6ade798273 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 8 Apr 2017 17:07:04 +0200 Subject: [PATCH 062/303] @B some fixes, also invoke regrename directly, @R use letter from -fbbb= --- gcc/bbb-opts.c | 347 ++++++++++++++++++++++++++++++++++++++++---------------- gcc/regrename.c | 12 +- 2 files changed, 260 insertions(+), 99 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index c525ae432071..737a5c00af3b 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -45,6 +45,7 @@ #include "emit-rtl.h" #include "tree-pass.h" #include "conditions.h" +#include "cselib.h" #include #include @@ -110,14 +111,14 @@ struct insn_info return t; } - inline insn_info - operator & (insn_info const & o) const - { - insn_info t; - t._use = _use & o._use; - t._def = _def & o._def; - return t; - } +// inline insn_info +// operator & (insn_info const & o) const +// { +// insn_info t; +// t._use = _use & o._use; +// t._def = _def & o._def; +// return t; +// } inline insn_info & operator |= (insn_info const & o) @@ -130,7 +131,7 @@ struct insn_info inline insn_info & operator &= (insn_info const & o) { - _use &= o._use; + _use &= o._use & o._def; _def &= o._def; return *this; } @@ -162,6 +163,18 @@ struct insn_info void scan (rtx); + + unsigned + get_def_mask () const + { + if (!_def || _def > 0xffff) + return 0; + + unsigned mask = _def - 1; + if (_def > 0xff) + mask &= 0xff00; + return mask; + } }; /* scan rtx for registers and set the corresponding flags. */ @@ -192,6 +205,47 @@ insn_info::scan (rtx x) } } +/* perform reg renaming. */ +static void +do_reg_rename (rtx x, unsigned oldregno, unsigned newregno) +{ + if (REG_P(x)) + { + if (REGNO(x) == oldregno) + df_ref_change_reg_with_loc (x, newregno); + return; + } + + if (x == cc0_rtx) + return; + + RTX_CODE code = GET_CODE(x); + const char *fmt = GET_RTX_FORMAT(code); + for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + do_reg_rename (XEXP(x, i), oldregno, newregno); + else if (fmt[i] == 'E') + for (int j = XVECLEN (x, i) - 1; j >= 0; j--) + do_reg_rename (XVECEXP(x, i, j), oldregno, newregno); + } +} + +static int +bit2regno (unsigned bit) +{ + if (!bit) + return -1; + + unsigned regno = 0; + while (!(bit & 1)) + { + ++regno; + bit >>= 1; + } + return regno; +} + /* * Collect some data. */ @@ -212,22 +266,25 @@ clear (void) infos.clear (); } +/* + * return true if the register is DEAD. + */ static bool is_reg_dead (unsigned regno, unsigned pos) { - if (pos >= infos.size ()) - return true; - - insn_info & ii0 = infos[pos++]; - if (!ii0.is_use (regno)) - return true; - - if (pos >= infos.size ()) - return true; - - insn_info & ii1 = infos[pos]; + for(;;) { + if (pos + 1 >= infos.size ()) + return true; + + rtx_insn * insn = insns[pos + 1]; + if (!LABEL_P(insn) && GET_CODE(insn) != USE) + break; + ++pos; + } - return !ii1.is_use (regno); + insn_info & ii0 = infos[pos + 1]; + // not dead if usage is reported in the next statement + return !ii0.is_use (regno); } /* @@ -242,6 +299,8 @@ dump_insns (char const * name) { insn_info & ii = infos[i]; + fprintf(stderr, "%d: ", i); + for (int j = 0; j < 8; ++j) if (ii.is_use (j)) fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j); @@ -301,6 +360,9 @@ update_meta_data () std::pair p = *todo.rbegin (); todo.pop_back (); +// fprintf(stderr, "%d ", p.first); +// dump_insns("update"); + insn_info ii = p.second; for (int pos = p.first; pos >= 0; --pos) @@ -655,9 +717,8 @@ propagate_moves () REGNO(srci), REGNO(dsti)); /* Move in front of loop and mark as dead. */ - remove_insn (ii); - add_insn_after (ii, before, 0); - add_reg_note (ii, REG_DEAD, srci); + rtx_insn * newii = make_insn_raw(PATTERN(ii)); + SET_INSN_DELETED(ii); /* Plus check if the reg was just loaded. */ if (bset) @@ -665,22 +726,31 @@ propagate_moves () rtx bdst = SET_DEST(bset); if (REG_P(bdst) && REGNO(bdst) == REGNO(srci)) { - SET_DEST(bset) = dsti; - SET_INSN_DELETED(ii); + SET_SRC(PATTERN(newii)) = SET_SRC(bset); +// SET_INSN_DELETED(ii); } } + else + add_reg_note (newii, REG_DEAD, srci); + + + add_insn_after (newii, before, 0); + /* Move behind loop - into next BB. */ - remove_insn (jj); - add_insn_before (jj, after, 0); + rtx_insn * newjj = make_insn_raw(PATTERN(jj)); + add_insn_before (newjj, after, 0); + SET_INSN_DELETED(jj); reg_reg.erase (j); reg_reg.erase (i); j = reg_reg.end (); inc = false; - df_insn_rescan (ii); - df_insn_rescan (jj); +// df_insn_rescan (ii); +// df_insn_rescan (jj); + df_insn_rescan (newii); + df_insn_rescan (newjj); /* add fixes if there were jumps out of the loop. */ if (jump_out.size ()) @@ -761,17 +831,11 @@ opt_strcpy () int num_clobbers_to_add = 0; int insn_code_number; - SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); - insn_code_number = recog (PATTERN (reg2x), reg2x, &num_clobbers_to_add); - - if (insn_code_number < 0 || !check_asm_operands (reg2x)) + rtx_insn * newinsn = make_insn_raw ( + gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg)))); + insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add); + if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn))) { - /* restore register. */ - SET_SRC(single_set(reg2x)) = SET_DEST(single_set (x2reg)); - } - else - { - rtx link; fprintf ( @@ -779,6 +843,8 @@ opt_strcpy () ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %d\n", REGNO(dst)); + SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); + for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1)) if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) { @@ -935,16 +1001,20 @@ commute_add_move (void) rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst); rtx newmem = replace_equiv_address_nv (dst, pinc); + rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src)); + if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn))) + continue; + if (validate_change (next, &SET_DEST(set2), newmem, 0)) { + fprintf (stderr, ":bbb: commute_add_move found\n"); + SET_INSN_DELETED(insn); - insn = emit_insn_before (gen_movsi (reg1dst, reg1src), next); + insn = emit_insn_before (newinsn, next); add_reg_note (next, REG_INC, reg1dst); - fprintf (stderr, ":bbb: commute_add_move found\n"); - df_insn_rescan (insn); df_insn_rescan (next); @@ -1037,18 +1107,11 @@ const_cmp_to_sub (void) rtx reg = dstp == left ? right : left; rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT (mode, intval)); - SET_SRC(setp) = plus; - SET_DEST(setp) = reg; + rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(reg, plus)); int num_clobbers_to_add = 0; - int insn_code_number = recog (PATTERN (prev), prev, &num_clobbers_to_add); - if (insn_code_number >= 0 && !check_asm_operands (prev)) - insn_code_number = -1; - - SET_SRC(setp) = srcp; - SET_DEST(setp) = dstp; - - if (insn_code_number < 0) + int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add); + if (insn_code_number >= 0 && !check_asm_operands (PATTERN (neuprev))) continue; // also convert current statement to cmp #0, reg @@ -1058,11 +1121,11 @@ const_cmp_to_sub (void) add_reg_note (insn, REG_DEAD, reg); SET_INSN_DELETED(prev); - neu = gen_rtx_SET(reg, plus); - prev = emit_insn_before (neu, insn); + prev = emit_insn_before (neuprev, insn); // urks - unknown side effects // int omitted_regno = REGNO(dstp); +// cselib_invalidate_rtx (dstp); // if (!(df->hard_regs_live_count[omitted_regno] -= 2)) // df_set_regs_ever_live (omitted_regno, false); @@ -1159,7 +1222,7 @@ elim_dead_assign (void) if (!REG_P(dst) || !REG_P(src)) continue; - if (!infos[index].is_use (REGNO(dst))) + if (is_reg_dead(REGNO(dst),index)) { fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst)); SET_INSN_DELETED(insn); @@ -1227,7 +1290,7 @@ merge_add (void) if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3)) continue; - fprintf (stderr, ": merge_add pattern found\n"); + fprintf (stderr, ":bbb: merge_add applied\n"); SET_SRC(set1) = l1; remove_insn (ins2); @@ -1242,60 +1305,82 @@ merge_add (void) static unsigned bb_reg_rename (void) { - unsigned change_count = 0; + dump_insns("bb_reg_rename"); for (unsigned index = 0; index < insns.size (); ++index) { - } - return change_count; -} + insn_info & ii = infos[index]; + const unsigned def = ii._def; + unsigned mask = ii.get_def_mask (); -/* Main entry point to the pass. */ -static unsigned int -execute_bbb_optimizations (void) -{ - df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN); - df_note_add_problem (); - df_analyze (); + if (!mask) + continue; - update_meta_data (); + std::vector found; + std::vector todo; + if (index + 1 < insns.size ()) + todo.push_back (index + 1); - for (;;) - { - int done = 1; - if (propagate_moves ()) - done = 0, update_meta_data (); + found.push_back (index); + /* a register was defined, follow all branches. */ + while (todo.size ()) + { + unsigned pos = todo[todo.size () - 1]; + todo.pop_back (); - if (offset_2_autoinc ()) - done = 0, update_meta_data (); + insn_info & jj = infos[pos]; + /* defined again. */ + if (jj._def & def) + continue; - if (opt_strcpy ()) - done = 0, update_meta_data (); + /* not referenced. */ + if (!(jj._use & def)) + continue; - if (commute_add_move ()) - done = 0, update_meta_data (); + /* update free regs. */ + mask &= ~jj._use; + if (!mask) + break; - if (const_cmp_to_sub ()) - done = 0, update_meta_data (); + found.push_back (pos); - if (merge_add ()) - done = 0, update_meta_data (); + /* follow jump and/or next insn. */ + rtx_insn * insn = insns[index]; + if (JUMP_P(insn)) + { + std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); + if (j != insn2index.end ()) + todo.push_back (j->second); - if (elim_dead_assign ()) - done = 0, update_meta_data (); + rtx jmppattern = PATTERN (insn); - if (bb_reg_rename ()) - done = 0, update_meta_data (); + rtx jmpsrc = XEXP(jmppattern, 1); + if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + } + else if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + } - if (done) - break; - } + if (mask) + { + int oldregno = bit2regno (def); + int newregno = bit2regno (mask); + fprintf (stderr, ":bbb: bb_reg_rename %d -> %d\n", oldregno, newregno); -// dump_insns ("bbb 1"); - clear (); + for (std::vector::iterator i = found.begin (); i != found.end (); ++i) + do_reg_rename (PATTERN (insns[*i]), oldregno, newregno); + cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); + cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); + return 1; + } + } return 0; } +extern class opt_pass * global_pass_regrename; + namespace { @@ -1315,7 +1400,7 @@ namespace { public: pass_bbb_optimizations (gcc::context *ctxt) : - rtl_opt_pass (pass_data_bbb_optimizations, ctxt) + rtl_opt_pass (pass_data_bbb_optimizations, ctxt), pp (0) { } @@ -1323,7 +1408,7 @@ namespace virtual bool gate (function *) { - return TARGET_AMIGA; // && flag_bbb_opts; + return TARGET_AMIGA && flag_bbb_opts; } virtual unsigned int @@ -1335,13 +1420,81 @@ namespace opt_pass * clone () { - return new pass_bbb_optimizations (m_ctxt); + pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt); + // bbb->pp = pp + 1; + return bbb; } + unsigned int pp; + + unsigned + execute_bbb_optimizations (void); }; // class pass_bbb_optimizations -}// anon namespace + + /* Main entry point to the pass. */ + unsigned + pass_bbb_optimizations::execute_bbb_optimizations (void) + { + df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN); + df_note_add_problem (); + df_analyze (); + + update_meta_data (); + + bool do_opt_strcpy = strchr(flag_bbb_opts, 's') || strchr(flag_bbb_opts, '*'); + bool do_commute_add_move = strchr(flag_bbb_opts, 'a') || strchr(flag_bbb_opts, '*'); + bool do_propagate_moves = strchr(flag_bbb_opts, 'p') || strchr(flag_bbb_opts, '*'); + bool do_const_cmp_to_sub = strchr(flag_bbb_opts, 'c') || strchr(flag_bbb_opts, '*'); + bool do_merge_add = strchr(flag_bbb_opts, 'm') || strchr(flag_bbb_opts, '*'); + bool do_elim_dead_assign = strchr(flag_bbb_opts, 'e') || strchr(flag_bbb_opts, '*'); + bool do_bb_reg_rename = strchr(flag_bbb_opts, 'r') || strchr(flag_bbb_opts, '*'); + + + for (;;) + { + int done = 1; + if (do_opt_strcpy && opt_strcpy ()) + done = 0, update_meta_data (); + + if (do_commute_add_move && commute_add_move ()) + done = 0, update_meta_data (); + + if (do_propagate_moves && propagate_moves ()) + done = 0, update_meta_data (); + +// if (offset_2_autoinc ()) +// done = 0, update_meta_data (); + + if (do_const_cmp_to_sub && const_cmp_to_sub ()) + done = 0, update_meta_data (); + + if (do_merge_add && merge_add ()) + done = 0, update_meta_data (); + + if (do_elim_dead_assign && elim_dead_assign ()) + done = 0, update_meta_data (); + +// if (do_bb_reg_rename && bb_reg_rename ()) +// done = 0, update_meta_data (); + if (done) + break; + } + + if (do_bb_reg_rename && ::global_pass_regrename) + { + class opt_pass * rr = ::global_pass_regrename->clone(); + rr->execute(0); + } + + if (strchr(flag_bbb_opts, 'X')) dump_insns ("bbb 1"); + clear (); + + return 0; + } + +} // anon namespace rtl_opt_pass * make_pass_bbb_optimizations (gcc::context * ctxt) diff --git a/gcc/regrename.c b/gcc/regrename.c index 4ba825e8d8e8..696e5557780e 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -1913,6 +1913,8 @@ regrename_optimize (void) return 0; } +class opt_pass * global_pass_regrename; + namespace { const pass_data pass_data_regrename = @@ -1927,13 +1929,14 @@ const pass_data pass_data_regrename = 0, /* todo_flags_start */ TODO_df_finish, /* todo_flags_finish */ }; - class pass_regrename : public rtl_opt_pass { public: pass_regrename (gcc::context *ctxt) : rtl_opt_pass (pass_data_regrename, ctxt) - {} + { + ::global_pass_regrename = this; + } /* opt_pass methods: */ virtual bool gate (function *) @@ -1943,6 +1946,11 @@ class pass_regrename : public rtl_opt_pass virtual unsigned int execute (function *) { return regrename_optimize (); } + opt_pass * clone () + { + return new pass_regrename(m_ctxt); + } + }; // class pass_regrename } // anon namespace From b747a5666a06f73ae8628788246f6d9e614f6393 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 10 Apr 2017 10:46:07 +0200 Subject: [PATCH 063/303] @B shrink_stack_frame starts working --- gcc/bbb-opts.c | 583 ++++++++++++++++++++++++++++++++++++++++++--------------- gcc/passes.def | 1 - 2 files changed, 427 insertions(+), 157 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 737a5c00af3b..6114e2fa5ed0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -111,15 +111,6 @@ struct insn_info return t; } -// inline insn_info -// operator & (insn_info const & o) const -// { -// insn_info t; -// t._use = _use & o._use; -// t._def = _def & o._def; -// return t; -// } - inline insn_info & operator |= (insn_info const & o) { @@ -250,6 +241,7 @@ bit2regno (unsigned bit) * Collect some data. */ static std::vector insns; +static std::vector temp; static std::vector jumps; static std::map insn2index; static std::vector infos; @@ -272,15 +264,16 @@ clear (void) static bool is_reg_dead (unsigned regno, unsigned pos) { - for(;;) { - if (pos + 1 >= infos.size ()) - return true; - - rtx_insn * insn = insns[pos + 1]; - if (!LABEL_P(insn) && GET_CODE(insn) != USE) - break; - ++pos; - } + for (;;) + { + if (pos + 1 >= infos.size ()) + return true; + + rtx_insn * insn = insns[pos + 1]; + if (!LABEL_P(insn) && GET_CODE(insn) != USE) + break; + ++pos; + } insn_info & ii0 = infos[pos + 1]; // not dead if usage is reported in the next statement @@ -292,14 +285,19 @@ is_reg_dead (unsigned regno, unsigned pos) * Sometimes used during debugging. */ static void -dump_insns (char const * name) +dump_insns (char const * name, bool all) { fprintf (stderr, "====================================: %s\n", name); + if (all) + { + for (rtx_insn * insn = get_insns (); insn && insn != insns[0]; insn = NEXT_INSN (insn)) + debug_rtx (insn); + } for (unsigned i = 0; i < insns.size (); ++i) { insn_info & ii = infos[i]; - fprintf(stderr, "%d: ", i); + fprintf (stderr, "%d: ", i); for (int j = 0; j < 8; ++j) if (ii.is_use (j)) @@ -314,6 +312,13 @@ dump_insns (char const * name) fprintf (stderr, "\t"); debug_rtx (insns[i]); + + if (all) + { + rtx_insn * p = i + 1 < insns.size () ? insns[i + 1] : 0; + for (rtx_insn * q = NEXT_INSN (insns[i]); q && q != p; q = NEXT_INSN (q)) + debug_rtx (q); + } } } @@ -321,7 +326,7 @@ dump_insns (char const * name) * Create a filtered view of insns - keep only those to work with. */ static void -update_meta_data () +update_insns () { rtx_insn *insn, *next; clear (); @@ -342,7 +347,11 @@ update_meta_data () insns.push_back (insn); } } +} +static void +update_insn_infos (void) +{ /* prepare insn_info */ insn_info ii; for (unsigned i = 0; i < insns.size (); ++i) @@ -360,14 +369,13 @@ update_meta_data () std::pair p = *todo.rbegin (); todo.pop_back (); -// fprintf(stderr, "%d ", p.first); -// dump_insns("update"); - insn_info ii = p.second; for (int pos = p.first; pos >= 0; --pos) { rtx_insn * insn = insns[pos]; + if (!insn) // moved to temp for stack frame cleanup + continue; if (pass && infos[pos].contains (ii)) break; @@ -487,7 +495,6 @@ update_meta_data () } ++pass; } - } /* @@ -717,7 +724,7 @@ propagate_moves () REGNO(srci), REGNO(dsti)); /* Move in front of loop and mark as dead. */ - rtx_insn * newii = make_insn_raw(PATTERN(ii)); + rtx_insn * newii = make_insn_raw (PATTERN (ii)); SET_INSN_DELETED(ii); /* Plus check if the reg was just loaded. */ @@ -733,12 +740,10 @@ propagate_moves () else add_reg_note (newii, REG_DEAD, srci); - add_insn_after (newii, before, 0); - /* Move behind loop - into next BB. */ - rtx_insn * newjj = make_insn_raw(PATTERN(jj)); + rtx_insn * newjj = make_insn_raw (PATTERN (jj)); add_insn_before (newjj, after, 0); SET_INSN_DELETED(jj); @@ -895,47 +900,6 @@ opt_strcpy () return change_count; } -/* - * Convert loops using a counting reg as offset with an address reg - * into a loop with auto inc address regs. - */ -static unsigned -offset_2_autoinc (void) -{ - unsigned change_count = 0; -#if 0 - rtx_insn * reg_const = 0; - - for (unsigned index = 0; index < insns.size (); ++index) - { - rtx_insn * insn = insns[index]; - - if (!next || !LABEL_P(next) || LABEL_NUSES(next) != 1) - continue; - - if (!NONJUMP_INSN_P(insn)) - continue; - - rtx use = single_set (insn); - if (!use) - continue; - - rtx reg = SET_DEST(use); - if (!REG_P(reg)) - continue; - - rtx val = SET_SRC(use); - -// fprintf(stderr, "possible start for offset_2_autoinc\n"); -// //debug_rtx(insn); -// //debug_rtx(next); - - } - -#endif - return change_count; -} - /* * convert * @@ -1052,7 +1016,7 @@ const_cmp_to_sub (void) { unsigned change_count = 0; #if HAVE_cc0 - for (unsigned index = 1; index + 1 < insns.size (); ++index) + for (unsigned index = insns.size () - 2; index > 0; --index) { rtx_insn * insn = insns[index]; rtx seti = single_set (insn); @@ -1072,13 +1036,13 @@ const_cmp_to_sub (void) if (!REG_P(left) || !REG_P(right)) continue; -// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) -// continue; - // TODO // FEATURE: check if the next uses are also a add/sub // then maybe that add/sub can be adjusted too + // if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) + // continue; + // use own reg_dead if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index)) continue; @@ -1222,7 +1186,7 @@ elim_dead_assign (void) if (!REG_P(dst) || !REG_P(src)) continue; - if (is_reg_dead(REGNO(dst),index)) + if (is_reg_dead (REGNO(dst), index)) { fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst)); SET_INSN_DELETED(insn); @@ -1278,8 +1242,8 @@ merge_add (void) continue; rtx l1 = XEXP(src1, 0); - rtx l2 = XEXP(src2, 0); - rtx l3 = XEXP(src3, 0); +// rtx l2 = XEXP(src2, 0); +// rtx l3 = XEXP(src3, 0); rtx r1 = XEXP(src1, 1); rtx r2 = XEXP(src2, 1); @@ -1293,89 +1257,393 @@ merge_add (void) fprintf (stderr, ":bbb: merge_add applied\n"); SET_SRC(set1) = l1; - remove_insn (ins2); - add_insn_after (ins2, ins3, 0); + rtx_insn * newins2 = make_insn_raw (PATTERN (ins2)); + add_insn_after (newins2, ins3, 0); + SET_INSN_DELETED(ins2); + df_insn_rescan (ins1); } return change_count; } -/* - * Always prefer lower register numbers within the class. +static void +clear_temp () +{ + for (unsigned i = 0; i < temp.size (); ++i) + if (temp[i]) + insns[i] = temp[i], temp[i] = 0; +} + +/** + * 1. scan for all used registers. + * 2. scan the stack from for omittable push/pop + * 3. adjust stack frame + insns referring to stack pointer + * typical code: + subq.l #4,sp + movem.l #16190,-(sp) + move.l 52(sp),d2 + move.l 56(sp),d3 + + * or + link a5,#4 + movem.l #16190,-(sp) + move.l 8(a5),d2 + move.l 12(a5),d3 + * + * => with a5 check only prolog/epilog + * => without a5 adjust insns referring sp if offset > startoffset + current sp diff + * + * startvalue count(pushes)*4 + * newstartvalue = startvalue - omitted pushes */ static unsigned -bb_reg_rename (void) +shrink_stack_frame (void) { - dump_insns("bb_reg_rename"); - for (unsigned index = 0; index < insns.size (); ++index) + /* nothing to do. */ + if (!insns.size ()) + return 0; + + temp.resize (insns.size ()); + + unsigned pos = 0; + rtx_insn * insn = insns[pos]; + if (JUMP_P(insn)) /* return -> empty function*/ + return 0; + + bool usea5 = false; + unsigned paramstart = 4; + /* + * Move prologue to temp. + * Only register push and parallel insn unless its a link a5 are moved. + */ + rtx_insn * prev = get_insns (); + for (; pos < insns.size ();) { - insn_info & ii = infos[index]; - const unsigned def = ii._def; - unsigned mask = ii.get_def_mask (); + insn = insns[pos]; - if (!mask) - continue; + /* check for prologue end. */ + for (; prev != insn; prev = NEXT_INSN (prev)) + if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_PROLOGUE_END) + break; + if (prev != insn) + break; + + rtx pattern = PATTERN (insn); + if (GET_CODE(pattern) == PARALLEL) + { + rtx set = XVECEXP(pattern, 0, 0); + rtx dst = SET_DEST(set); + /* ignore link a5 */ + if (REG_P(dst) && REGNO(dst) == 13) + usea5 = true; + else + { + /* use movem */ + temp[pos] = insn; + insns[pos] = 0; + } + ++pos; + continue; + } + if (GET_CODE(pattern) != SET) + { + ++pos; + continue; + } + + /* move only the push statements. */ + rtx src = SET_SRC(pattern); + rtx dest = SET_DEST(pattern); + if (REG_P(src)) + { + if (MEM_P(dest)) + { + rtx predec = XEXP(dest, 0); + if (GET_CODE(predec) == PRE_DEC) + { + rtx reg = XEXP(predec, 0); + if (REG_P(reg) && REGNO(reg) == 15) + { + temp[pos] = insn; + insns[pos] = 0; + } + } + } + } + else if (GET_CODE(src) == PLUS && REG_P(dest) && REGNO(dest) == 15) + { + /* check for stack variables. */ + rtx reg = XEXP(src, 0); + rtx cx = XEXP(src, 1); + if (REG_P(reg) && REGNO(reg) == 15 && CONST_INT_P(cx)) + paramstart -= INTVAL(cx); + } + + if (++pos >= insns.size ()) + { + clear_temp (); + return 0; + } + } - std::vector found; - std::vector todo; - if (index + 1 < insns.size ()) - todo.push_back (index + 1); + if (pos == 0) + return 0; + + unsigned prologueend = pos; - found.push_back (index); - /* a register was defined, follow all branches. */ - while (todo.size ()) + /* search epilogues - there can be multiple epilogues. */ + while (pos < insns.size ()) + { + while (pos < insns.size ()) { - unsigned pos = todo[todo.size () - 1]; - todo.pop_back (); + insn = insns[pos]; + for (; prev != insn; prev = NEXT_INSN (prev)) + if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_EPILOGUE_BEG) + break; - insn_info & jj = infos[pos]; - /* defined again. */ - if (jj._def & def) - continue; + if (prev != insn) + break; - /* not referenced. */ - if (!(jj._use & def)) - continue; + ++pos; + } - /* update free regs. */ - mask &= ~jj._use; - if (!mask) + /* move epilogues away. */ + for (; pos < insns.size (); ++pos) + { + insn = insns[pos]; + if (JUMP_P(insn)) /* return */ break; - found.push_back (pos); + if (LABEL_P(insn)) + break; - /* follow jump and/or next insn. */ - rtx_insn * insn = insns[index]; - if (JUMP_P(insn)) + /* omitt the frame pointer a5. */ + rtx pattern = PATTERN (insn); + if (GET_CODE(pattern) == PARALLEL) { - std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); - if (j != insn2index.end ()) - todo.push_back (j->second); + rtx set = XVECEXP(pattern, 0, 0); + rtx dst = SET_DEST(set); + /* unlink is last. */ + if (REG_P(dst) && REGNO(dst) == 13) + break; + + /* movem. */ + temp[pos] = insn; + insns[pos] = 0; + } + else if (GET_CODE(pattern) == SET) + { + /* check for move (a7+), x */ + rtx src = SET_SRC(pattern); + rtx dst = SET_DEST(pattern); + if (REG_P(dst)) + { + if (MEM_P(src)) + { + rtx postinc = XEXP(src, 0); + if (GET_CODE(postinc) == POST_INC) + { + rtx reg = XEXP(postinc, 0); + if (REG_P(reg) && REGNO(reg) == 15) + { + temp[pos] = insn; + insns[pos] = 0; + } + } + } + } + } + } + ++pos; + } + /* gather usage stats without prologue/epilogue */ + update_insn_infos (); + insn_info ii; + for (unsigned i = 0; i < infos.size (); ++i) + ii |= infos[i]; + unsigned freemask = ~ii._use; - rtx jmppattern = PATTERN (insn); + rtx a7 = gen_raw_REG (SImode, 15); - rtx jmpsrc = XEXP(jmppattern, 1); - if (GET_CODE(jmpsrc) == IF_THEN_ELSE) - if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); + unsigned adjust = 0; + /* now all push/pop insns are in temp. */ + for (unsigned i = 0; i < temp.size (); ++i) + { + insn = temp[i]; + if (!insn) + continue; + + rtx pattern = PATTERN (insn); + /* check the pushed regs, either a vector or single statements */ + if (GET_CODE(pattern) == PARALLEL) + { + std::vector regs; + std::vector clobbers; + for (int j = 0; j < XVECLEN(pattern, 0); ++j) + { + rtx set = XVECEXP(pattern, 0, j); + if (GET_CODE(set) == CLOBBER) + { + clobbers.push_back (set); + continue; + } + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); + rtx reg; + if (MEM_P(src)) + reg = dst; + else if (MEM_P(dst)) + reg = src; + else + continue; + + if (i < prologueend) + paramstart += 4; + unsigned regbit = 1 << REGNO(reg); + if (freemask & regbit) + { + fprintf (stderr, i < prologueend ? "remove push for %d\n" : "remove pop for %d\n", REGNO(reg)); + if (i < prologueend) + adjust += 4; + } + else + regs.push_back (reg); + } + + /* don't touch - clobbers! */ + if (clobbers.size()) + continue; + + if ((int) regs.size () + 1 < XVECLEN(pattern, 0) || regs.size () <= 2) + { + if (regs.size () <= 2) + { + for (unsigned k = 0; k < regs.size (); ++k) + { + rtx reg = regs[k]; + if (i < prologueend) + { + /* push */ + rtx dec = gen_rtx_PRE_DEC(SImode, a7); + rtx mem = gen_rtx_MEM (SImode, dec); + rtx set = gen_rtx_SET(mem, reg); + emit_insn_after (set, insn); + } + else + { + /* pop */ + rtx dec = gen_rtx_POST_INC(SImode, a7); + rtx mem = gen_rtx_MEM (SImode, dec); + rtx set = gen_rtx_SET(reg, mem); + emit_insn_before (set, insn); + } + } + } + else + { + rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + 1)); + int x = regs.size () * 4 + 4; + + rtx plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); + XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus); + + if (i >= prologueend) + x = 0; + + for (unsigned k = 0; k < regs.size (); ++k) + { + if (i < prologueend) + { + /* push */ + plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x)); + x -= 4; + rtx mem = gen_rtx_MEM (SImode, plus); + rtx set = gen_rtx_SET(mem, regs[k]); + XVECEXP(parallel, 0, k + 1) = set; + } + else + { + /* pop */ + plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; + x += 4; + rtx mem = gen_rtx_MEM (SImode, plus); + rtx set = gen_rtx_SET(regs[k], mem); + XVECEXP(parallel, 0, k + 1) = set; + } + } + emit_insn_after (parallel, insn); + } + SET_INSN_DELETED(insn); + } + } + else + { + rtx set = PATTERN (insn); + + if (i < prologueend) + { + /* move x,-(a7). */ + paramstart += 4; + rtx src = SET_SRC(set); + unsigned regbit = 1 << REGNO(src); + if (freemask & regbit) + { + adjust += 4; + fprintf (stderr, "remove push for %d\n", REGNO(src)); + SET_INSN_DELETED(insn); + } + } + else + { + /* move (a7)+,x */ + rtx dst = SET_DEST(set); + unsigned regbit = 1 << REGNO(dst); + if (freemask & regbit) + { + fprintf (stderr, "remove pop for %d\n", REGNO(dst)); + SET_INSN_DELETED(insn); + } } - else if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); } + } - if (mask) + /* fix sp offsets. */ + if (!usea5 && adjust) + { + for (unsigned index = 0; index < insns.size (); ++index) { - int oldregno = bit2regno (def); - int newregno = bit2regno (mask); - fprintf (stderr, ":bbb: bb_reg_rename %d -> %d\n", oldregno, newregno); + insn = insns[index]; + if (!insn || !INSN_P(insn)) + continue; - for (std::vector::iterator i = found.begin (); i != found.end (); ++i) - do_reg_rename (PATTERN (insns[*i]), oldregno, newregno); + rtx set = single_set (insn); + if (!set) + continue; - cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); - cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); - return 1; + rtx mem = SET_SRC(set); + if (MEM_P(mem)) + { + rtx plus = XEXP(mem, 0); + if (GET_CODE(plus) == PLUS) + { + rtx sp = XEXP(plus, 0); + if (REG_P(sp) && REGNO(sp) == 15) + { + rtx c = XEXP(plus, 1); + if (CONST_INT_P(c)) + { + int n = INTVAL(c); + if (n >= paramstart) + XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, n - adjust); + } + } + } + } } } + + /* restore stack insns */ + clear_temp (); + return 0; } @@ -1420,7 +1688,7 @@ namespace opt_pass * clone () { - pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt); + pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt); // bbb->pp = pp + 1; return bbb; } @@ -1432,7 +1700,6 @@ namespace }; // class pass_bbb_optimizations - /* Main entry point to the pass. */ unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) @@ -1441,54 +1708,58 @@ namespace df_note_add_problem (); df_analyze (); - update_meta_data (); - - bool do_opt_strcpy = strchr(flag_bbb_opts, 's') || strchr(flag_bbb_opts, '*'); - bool do_commute_add_move = strchr(flag_bbb_opts, 'a') || strchr(flag_bbb_opts, '*'); - bool do_propagate_moves = strchr(flag_bbb_opts, 'p') || strchr(flag_bbb_opts, '*'); - bool do_const_cmp_to_sub = strchr(flag_bbb_opts, 'c') || strchr(flag_bbb_opts, '*'); - bool do_merge_add = strchr(flag_bbb_opts, 'm') || strchr(flag_bbb_opts, '*'); - bool do_elim_dead_assign = strchr(flag_bbb_opts, 'e') || strchr(flag_bbb_opts, '*'); - bool do_bb_reg_rename = strchr(flag_bbb_opts, 'r') || strchr(flag_bbb_opts, '*'); + update_insns (); + bool do_opt_strcpy = strchr (flag_bbb_opts, 's') || strchr (flag_bbb_opts, '*'); + bool do_commute_add_move = strchr (flag_bbb_opts, 'a') || strchr (flag_bbb_opts, '*'); + bool do_propagate_moves = strchr (flag_bbb_opts, 'p') || strchr (flag_bbb_opts, '*'); + bool do_const_cmp_to_sub = strchr (flag_bbb_opts, 'c') || strchr (flag_bbb_opts, '*'); + bool do_merge_add = strchr (flag_bbb_opts, 'm') || strchr (flag_bbb_opts, '*'); + bool do_elim_dead_assign = strchr (flag_bbb_opts, 'e') || strchr (flag_bbb_opts, '*'); + bool do_bb_reg_rename = strchr (flag_bbb_opts, 'r') || strchr (flag_bbb_opts, '*'); + bool do_shrink_stack_frame = strchr (flag_bbb_opts, 'f') || strchr (flag_bbb_opts, '*'); for (;;) { int done = 1; if (do_opt_strcpy && opt_strcpy ()) - done = 0, update_meta_data (); + done = 0, update_insns (); if (do_commute_add_move && commute_add_move ()) - done = 0, update_meta_data (); + done = 0, update_insns (); if (do_propagate_moves && propagate_moves ()) - done = 0, update_meta_data (); - -// if (offset_2_autoinc ()) -// done = 0, update_meta_data (); + done = 0, update_insns (); + update_insn_infos (); if (do_const_cmp_to_sub && const_cmp_to_sub ()) - done = 0, update_meta_data (); + done = 0, update_insns (), update_insn_infos (); if (do_merge_add && merge_add ()) - done = 0, update_meta_data (); + done = 0, update_insns (), update_insn_infos (); if (do_elim_dead_assign && elim_dead_assign ()) - done = 0, update_meta_data (); + done = 0, update_insns (); -// if (do_bb_reg_rename && bb_reg_rename ()) -// done = 0, update_meta_data (); if (done) break; } if (do_bb_reg_rename && ::global_pass_regrename) { - class opt_pass * rr = ::global_pass_regrename->clone(); - rr->execute(0); + class opt_pass * rr = ::global_pass_regrename->clone (); + rr->execute (0); + update_insns (); + } + + if (do_shrink_stack_frame) + { + shrink_stack_frame (); + update_insns (); } - if (strchr(flag_bbb_opts, 'X')) dump_insns ("bbb 1"); + if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x')) + dump_insns ("bbb 1", strchr (flag_bbb_opts, 'X')); clear (); return 0; diff --git a/gcc/passes.def b/gcc/passes.def index ca5b94552d4e..5b78cbd7fb38 100644 --- gcc/passes.def +++ gcc/passes.def @@ -446,7 +446,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_split_after_reload); NEXT_PASS (pass_ree); NEXT_PASS (pass_compare_elim_after_reload); - NEXT_PASS (pass_bbb_optimizations); NEXT_PASS (pass_branch_target_load_optimize1); NEXT_PASS (pass_jump2); NEXT_PASS (pass_duplicate_computed_gotos); From dcfedefbc4883ebaf068b40920b7830971d02923 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Apr 2017 18:01:13 +0200 Subject: [PATCH 064/303] @B various bugs, shrink stack frame supports also fp-regs --- gcc/bbb-opts.c | 300 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 238 insertions(+), 62 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 6114e2fa5ed0..c688ca8ae192 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -43,9 +43,11 @@ #include "recog.h" #include "cfgrtl.h" #include "emit-rtl.h" +#include "tree.h" #include "tree-pass.h" #include "conditions.h" #include "cselib.h" +#include "langhooks.h" #include #include @@ -158,10 +160,16 @@ struct insn_info unsigned get_def_mask () const { - if (!_def || _def > 0xffff) + if (!_def || _def > 0x7fff) return 0; unsigned mask = _def - 1; + /* more than one register -> don't touch. */ + if ((mask & ~_def) != mask) + return 0; + + if (_def > 0x1000) + return 0; if (_def > 0xff) mask &= 0xff00; return mask; @@ -349,6 +357,19 @@ update_insns () } } +extern struct lang_hooks lang_hooks; +extern tree current_function_decl; +static char const * +getCurrentFunctionName () +{ + static char fxname[512]; + if (current_function_decl == NULL) + strcpy (fxname, ""); + else + strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2)); + return fxname; +} + static void update_insn_infos (void) { @@ -401,24 +422,44 @@ update_insn_infos (void) if (CALL_P(insn)) { + insn_info def; + insn_info use; + /* a call sets d0 and maybe also d1,a0,a1. */ - ii.unset (0); - ii.unset (1); - ii.unset (8); - ii.unset (9); + if (ii.is_use(0)) + def.def (0); + if (ii.is_use (1)) + { + fprintf (stderr, ":bbb: use of d1 after call in %s\n", getCurrentFunctionName ()); + def.def (1); + } + if (ii.is_use (8)) + { + fprintf (stderr, ":bbb: use of a0 after call in %s\n", getCurrentFunctionName ()); + def.def (8); + } + if (ii.is_use (9)) + { + fprintf (stderr, ":bbb: use of a1 after call in %s\n", getCurrentFunctionName ()); + def.def (9); + } // FIXME: isuse the DECL and read attributes. // use regs depending on flag mregparm for (int i = 0; i < amigaos_regparm; ++i) { - ii.use (i); - ii.use (i + 8); + use.use (i); + use.use (i + 8); } // check for reg use - ii.scan (pattern); + use.scan (pattern); + + infos[pos] = def | use | ii; + + ii &= ~def; + ii |= use; - infos[pos] = ii; continue; } @@ -720,8 +761,9 @@ propagate_moves () rtx_insn * after = insns[index + 1]; rtx bset = single_set (before); - fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %d, %d\n", - REGNO(srci), REGNO(dsti)); + fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %s, %s\n", + reg_names[REGNO(srci)], + reg_names[REGNO(dsti)]); /* Move in front of loop and mark as dead. */ rtx_insn * newii = make_insn_raw (PATTERN (ii)); @@ -752,8 +794,6 @@ propagate_moves () j = reg_reg.end (); inc = false; -// df_insn_rescan (ii); -// df_insn_rescan (jj); df_insn_rescan (newii); df_insn_rescan (newjj); @@ -813,11 +853,17 @@ opt_strcpy () rtx_insn * insn = insns[index]; if (!NONJUMP_INSN_P(insn)) - continue; + { + x2reg = 0; + continue; + } rtx set = single_set (insn); if (!set) - continue; + { + x2reg = 0; + continue; + } if (x2reg && reg2x) { @@ -845,8 +891,8 @@ opt_strcpy () fprintf ( stderr, - ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %d\n", - REGNO(dst)); + ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", + reg_names[REGNO(dst)]); SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); @@ -1040,15 +1086,12 @@ const_cmp_to_sub (void) // FEATURE: check if the next uses are also a add/sub // then maybe that add/sub can be adjusted too - // if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) - // continue; - // use own reg_dead +// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) +// continue; + /* use own reg_dead - reg_notes seem to be inaccurate!? */ if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index)) continue; - fprintf (stderr, ":bbb: found reg-reg compare with both dead: %d %d\n", is_reg_dead (REGNO(left), index), - is_reg_dead (REGNO(right), index)); - // maybe add a search? rtx_insn * prev = insns[index - 1]; rtx setp = single_set (prev); @@ -1087,12 +1130,6 @@ const_cmp_to_sub (void) SET_INSN_DELETED(prev); prev = emit_insn_before (neuprev, insn); -// urks - unknown side effects -// int omitted_regno = REGNO(dstp); -// cselib_invalidate_rtx (dstp); -// if (!(df->hard_regs_live_count[omitted_regno] -= 2)) -// df_set_regs_ever_live (omitted_regno, false); - fprintf (stderr, ":bbb: const_cmp_to_sub replaced reg-reg compare with sub\n"); if (dstp != left) @@ -1188,7 +1225,7 @@ elim_dead_assign (void) if (is_reg_dead (REGNO(dst), index)) { - fprintf (stderr, ":bbb: elim_dead_assign to %d\n", REGNO(dst)); + fprintf (stderr, ":bbb: elim_dead_assign to %s\n", reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); ++change_count; } @@ -1311,6 +1348,8 @@ shrink_stack_frame (void) bool usea5 = false; unsigned paramstart = 4; + int a5offset = 0; + /* * Move prologue to temp. * Only register push and parallel insn unless its a link a5 are moved. @@ -1333,8 +1372,12 @@ shrink_stack_frame (void) rtx set = XVECEXP(pattern, 0, 0); rtx dst = SET_DEST(set); /* ignore link a5 */ - if (REG_P(dst) && REGNO(dst) == 13) - usea5 = true; + if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) + { + usea5 = true; + set = XVECEXP(pattern, 0, 2); + a5offset = INTVAL(XEXP(SET_SRC(set), 1)); + } else { /* use movem */ @@ -1361,7 +1404,7 @@ shrink_stack_frame (void) if (GET_CODE(predec) == PRE_DEC) { rtx reg = XEXP(predec, 0); - if (REG_P(reg) && REGNO(reg) == 15) + if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM) { temp[pos] = insn; insns[pos] = 0; @@ -1369,12 +1412,12 @@ shrink_stack_frame (void) } } } - else if (GET_CODE(src) == PLUS && REG_P(dest) && REGNO(dest) == 15) + else if (GET_CODE(src) == PLUS && REG_P(dest) && REGNO(dest) == STACK_POINTER_REGNUM) { /* check for stack variables. */ rtx reg = XEXP(src, 0); rtx cx = XEXP(src, 1); - if (REG_P(reg) && REGNO(reg) == 15 && CONST_INT_P(cx)) + if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM && CONST_INT_P(cx)) paramstart -= INTVAL(cx); } @@ -1390,6 +1433,8 @@ shrink_stack_frame (void) unsigned prologueend = pos; + prev = insn; + /* search epilogues - there can be multiple epilogues. */ while (pos < insns.size ()) { @@ -1406,6 +1451,7 @@ shrink_stack_frame (void) ++pos; } + /* move epilogues away. */ for (; pos < insns.size (); ++pos) { @@ -1423,7 +1469,7 @@ shrink_stack_frame (void) rtx set = XVECEXP(pattern, 0, 0); rtx dst = SET_DEST(set); /* unlink is last. */ - if (REG_P(dst) && REGNO(dst) == 13) + if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) break; /* movem. */ @@ -1443,7 +1489,7 @@ shrink_stack_frame (void) if (GET_CODE(postinc) == POST_INC) { rtx reg = XEXP(postinc, 0); - if (REG_P(reg) && REGNO(reg) == 15) + if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM) { temp[pos] = insn; insns[pos] = 0; @@ -1453,6 +1499,7 @@ shrink_stack_frame (void) } } } + prev = insn; ++pos; } /* gather usage stats without prologue/epilogue */ @@ -1462,7 +1509,8 @@ shrink_stack_frame (void) ii |= infos[i]; unsigned freemask = ~ii._use; - rtx a7 = gen_raw_REG (SImode, 15); + rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM); + rtx a5 = gen_raw_REG (SImode, FRAME_POINTER_REGNUM); unsigned adjust = 0; /* now all push/pop insns are in temp. */ @@ -1501,7 +1549,8 @@ shrink_stack_frame (void) unsigned regbit = 1 << REGNO(reg); if (freemask & regbit) { - fprintf (stderr, i < prologueend ? "remove push for %d\n" : "remove pop for %d\n", REGNO(reg)); + fprintf (stderr, i < prologueend ? ":bbb: remove push for %s\n" : ":bbb: remove pop for %s\n", + reg_names[REGNO(reg)]); if (i < prologueend) adjust += 4; } @@ -1510,11 +1559,12 @@ shrink_stack_frame (void) } /* don't touch - clobbers! */ - if (clobbers.size()) + if (clobbers.size ()) continue; if ((int) regs.size () + 1 < XVECLEN(pattern, 0) || regs.size () <= 2) { + fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0), regs.size () + 1); if (regs.size () <= 2) { for (unsigned k = 0; k < regs.size (); ++k) @@ -1523,16 +1573,16 @@ shrink_stack_frame (void) if (i < prologueend) { /* push */ - rtx dec = gen_rtx_PRE_DEC(SImode, a7); - rtx mem = gen_rtx_MEM (SImode, dec); + rtx dec = gen_rtx_PRE_DEC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); + rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec); rtx set = gen_rtx_SET(mem, reg); emit_insn_after (set, insn); } else { /* pop */ - rtx dec = gen_rtx_POST_INC(SImode, a7); - rtx mem = gen_rtx_MEM (SImode, dec); + rtx dec = gen_rtx_POST_INC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); + rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec); rtx set = gen_rtx_SET(reg, mem); emit_insn_before (set, insn); } @@ -1540,14 +1590,24 @@ shrink_stack_frame (void) } else { - rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + 1)); - int x = regs.size () * 4 + 4; + /* add romm for add. */ + int add1 = i < prologueend || !usea5 ? 1 : 0; + rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1)); + rtx plus; + + int x = 0; + for (unsigned k = 0; k < regs.size (); ++k) + x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; - rtx plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); - XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus); + /* no add if a5 is used with pop */ + if (!usea5 || i < prologueend) + { + plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); + XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus); + } if (i >= prologueend) - x = 0; + x = usea5 ? -x : 0; for (unsigned k = 0; k < regs.size (); ++k) { @@ -1555,19 +1615,30 @@ shrink_stack_frame (void) { /* push */ plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x)); - x -= 4; - rtx mem = gen_rtx_MEM (SImode, plus); + x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; + rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); rtx set = gen_rtx_SET(mem, regs[k]); XVECEXP(parallel, 0, k + 1) = set; } else { /* pop */ - plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; - x += 4; - rtx mem = gen_rtx_MEM (SImode, plus); - rtx set = gen_rtx_SET(regs[k], mem); - XVECEXP(parallel, 0, k + 1) = set; + if (usea5) + { + x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; + plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); + rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); + rtx set = gen_rtx_SET(regs[k], mem); + XVECEXP(parallel, 0, k) = set; + } + else + { + plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; + x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; + rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); + rtx set = gen_rtx_SET(regs[k], mem); + XVECEXP(parallel, 0, k + 1) = set; + } } } emit_insn_after (parallel, insn); @@ -1582,13 +1653,13 @@ shrink_stack_frame (void) if (i < prologueend) { /* move x,-(a7). */ - paramstart += 4; rtx src = SET_SRC(set); + paramstart += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; unsigned regbit = 1 << REGNO(src); if (freemask & regbit) { - adjust += 4; - fprintf (stderr, "remove push for %d\n", REGNO(src)); + adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; + fprintf (stderr, ":bbb: remove push for %s\n", reg_names[REGNO(src)]); SET_INSN_DELETED(insn); } } @@ -1599,7 +1670,7 @@ shrink_stack_frame (void) unsigned regbit = 1 << REGNO(dst); if (freemask & regbit) { - fprintf (stderr, "remove pop for %d\n", REGNO(dst)); + fprintf (stderr, ":bbb: remove pop for %s\n", reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); } } @@ -1626,7 +1697,7 @@ shrink_stack_frame (void) if (GET_CODE(plus) == PLUS) { rtx sp = XEXP(plus, 0); - if (REG_P(sp) && REGNO(sp) == 15) + if (REG_P(sp) && REGNO(sp) == STACK_POINTER_REGNUM) { rtx c = XEXP(plus, 1); if (CONST_INT_P(c)) @@ -1647,6 +1718,99 @@ shrink_stack_frame (void) return 0; } +/* + * Always prefer lower register numbers within the class. + */ +static unsigned +bb_reg_rename (void) +{ + for (unsigned index = 0; index < insns.size (); ++index) + { + insn_info & ii = infos[index]; + const unsigned def = ii._def; + unsigned mask = ii.get_def_mask (); + + if (!mask) + continue; + + std::vector found; + std::vector todo; + if (index + 1 < insns.size ()) + todo.push_back (index + 1); + + found.push_back (index); + /* a register was defined, follow all branches. */ + while (todo.size ()) + { + unsigned pos = todo[todo.size () - 1]; + todo.pop_back (); + + if (LABEL_P(insns[pos])) + { + if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + continue; + } + + insn_info & jj = infos[pos]; + + /* update free regs. */ + mask &= ~jj._use; + mask &= ~jj._def; + if (!mask) + break; + + /* defined again. */ + if (jj._def & def) + continue; + + /* not referenced. */ + if (!(jj._use & def)) + continue; + + found.push_back (pos); + + /* follow jump and/or next insn. */ + rtx_insn * insn = insns[pos]; + if (JUMP_P(insn)) + { + std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); + if (j != insn2index.end ()) + todo.push_back (j->second); + + rtx jmppattern = PATTERN (insn); + + rtx jmpsrc = XEXP(jmppattern, 1); + if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + } + else if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + } + + if (mask) + { + int oldregno = bit2regno (def); + int newregno = bit2regno (mask); + fprintf (stderr, ":bbb: bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], + found.size ()); + + for (std::vector::iterator i = found.begin (); i != found.end (); ++i) + { + debug_rtx (insns[*i]); + do_reg_rename (PATTERN (insns[*i]), oldregno, newregno); + } + + cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); + cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); + return 1; + } + } + return 0; +} + +extern const char * current_function_func_begin_label; extern class opt_pass * global_pass_regrename; namespace @@ -1676,7 +1840,10 @@ namespace virtual bool gate (function *) { - return TARGET_AMIGA && flag_bbb_opts; + if (!flag_bbb_opts) + flag_bbb_opts = "*"; + + return TARGET_AMIGA && optimize > 0 && flag_bbb_opts; } virtual unsigned int @@ -1704,6 +1871,10 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { + + if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x')) + fprintf (stderr, "%s:\n", current_function_func_begin_label); + df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN); df_note_add_problem (); df_analyze (); @@ -1749,6 +1920,11 @@ namespace { class opt_pass * rr = ::global_pass_regrename->clone (); rr->execute (0); + +// update_insns (); +// update_insn_infos (); +// bb_reg_rename (); + update_insns (); } From 56aa60f1154c2988edf35ba30ec259a798ba61f2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 13 Apr 2017 23:49:13 +0200 Subject: [PATCH 065/303] @B fix stack frame handling and suspicious other stuff --- gcc/bbb-opts.c | 80 ++++++++++++++++++++++++++++++---------------------------- gcc/final.c | 7 ++++- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index c688ca8ae192..56251b906184 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -182,7 +182,8 @@ insn_info::scan (rtx x) { if (REG_P(x)) { - use (REGNO(x)); + for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r) + use (r); return; } @@ -425,35 +426,34 @@ update_insn_infos (void) insn_info def; insn_info use; - /* a call sets d0 and maybe also d1,a0,a1. */ - if (ii.is_use(0)) - def.def (0); - if (ii.is_use (1)) - { - fprintf (stderr, ":bbb: use of d1 after call in %s\n", getCurrentFunctionName ()); - def.def (1); - } - if (ii.is_use (8)) + /* add mregparm registers. */ + for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1)) { - fprintf (stderr, ":bbb: use of a0 after call in %s\n", getCurrentFunctionName ()); - def.def (8); - } - if (ii.is_use (9)) - { - fprintf (stderr, ":bbb: use of a1 after call in %s\n", getCurrentFunctionName ()); - def.def (9); + rtx op, reg; + + if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) + for (int r = REGNO(reg); r <= END_REGNO (reg); ++r) + use.use (r); } - // FIXME: isuse the DECL and read attributes. - // use regs depending on flag mregparm - for (int i = 0; i < amigaos_regparm; ++i) + rtx set = single_set (insn); + if (set) { - use.use (i); - use.use (i + 8); + use.scan (SET_SRC(set)); + def.scan (SET_DEST(set)); } + else + use.scan (pattern); - // check for reg use - use.scan (pattern); + /* fix missing defs - a call sets d0 and maybe also d1,a0,a1. */ + if (ii.is_use (0)) + def.def (0); + if (ii.is_use (1)) + def.def (1); + if (ii.is_use (8)) + def.def (8); + if (ii.is_use (9)) + def.def (9); infos[pos] = def | use | ii; @@ -494,7 +494,7 @@ update_insn_infos (void) continue; } - if (GET_CODE (pattern) != PARALLEL) + if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER) { fprintf (stderr, "##### "); debug_rtx (insn); @@ -1062,7 +1062,7 @@ const_cmp_to_sub (void) { unsigned change_count = 0; #if HAVE_cc0 - for (unsigned index = insns.size () - 2; index > 0; --index) + for (int index = insns.size () - 2; index > 0; --index) { rtx_insn * insn = insns[index]; rtx seti = single_set (insn); @@ -1079,7 +1079,7 @@ const_cmp_to_sub (void) rtx left = XEXP(srci, 0); rtx right = XEXP(srci, 1); - if (!REG_P(left) || !REG_P(right)) + if (!REG_P(left) || !REG_P(right) || REG_NREGS(left) > 1 || REG_NREGS(right) > 1) continue; // TODO @@ -1451,7 +1451,6 @@ shrink_stack_frame (void) ++pos; } - /* move epilogues away. */ for (; pos < insns.size (); ++pos) { @@ -1506,7 +1505,12 @@ shrink_stack_frame (void) update_insn_infos (); insn_info ii; for (unsigned i = 0; i < infos.size (); ++i) - ii |= infos[i]; + { + insn_info & jj = infos[i]; + ii |= jj; +// fprintf (stderr, "%08lx %08lx\n", jj._use, jj._def); + } +// fprintf (stderr, "%08lx %08lx\n", ii._use, ii._def); unsigned freemask = ~ii._use; rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM); @@ -1562,9 +1566,15 @@ shrink_stack_frame (void) if (clobbers.size ()) continue; - if ((int) regs.size () + 1 < XVECLEN(pattern, 0) || regs.size () <= 2) + /* add romm for add. + * push is always using -(a7) addressing. + * If a5 is used a movem offset(a5) is generated to pop saved registers.. + * Otherwise a7 is used and with (a7)+ addressing. + */ + int add1 = i < prologueend || !usea5 ? 1 : 0; + if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2) { - fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0), regs.size () + 1); + fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); if (regs.size () <= 2) { for (unsigned k = 0; k < regs.size (); ++k) @@ -1590,8 +1600,6 @@ shrink_stack_frame (void) } else { - /* add romm for add. */ - int add1 = i < prologueend || !usea5 ? 1 : 0; rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1)); rtx plus; @@ -1856,7 +1864,7 @@ namespace clone () { pass_bbb_optimizations * bbb = new pass_bbb_optimizations (m_ctxt); - // bbb->pp = pp + 1; + bbb->pp = pp + 1; return bbb; } @@ -1871,10 +1879,6 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { - - if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x')) - fprintf (stderr, "%s:\n", current_function_func_begin_label); - df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN); df_note_add_problem (); df_analyze (); diff --git a/gcc/final.c b/gcc/final.c index 55cf509611f7..9d21ffc1baff 100644 --- gcc/final.c +++ gcc/final.c @@ -2165,7 +2165,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, /* Ignore deleted insns. These can occur when we split insns (due to a template of "#") while not optimizing. */ - if (insn->deleted ()) + if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED) return NEXT_INSN (insn); switch (GET_CODE (insn)) @@ -4430,12 +4430,17 @@ leaf_renumber_regs_insn (rtx in_rtx) } #endif + +extern void dump_insns(char const *); + /* Turn the RTL into assembly. */ static unsigned int rest_of_handle_final (void) { const char *fnname = get_fnname_from_decl (current_function_decl); +// dump_insns("final"); + assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); final (get_insns (), asm_out_file, optimize); From 51c5b7b668483ac0cdc30a3fee718754a03bcca9 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 14 Apr 2017 18:33:26 +0200 Subject: [PATCH 066/303] @R add option description for command line help --- gcc/config/m68k/amigaos.opt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index a5a14449dea9..9c08ba43196e 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -25,24 +25,24 @@ small code model fbaserel Target Report Var(flag_pic,3) -data is adressed relativ to a4 +data is addressed relative to a4 fbaserel32 Target Report Var(flag_pic,4) -data is adressed relativ to a4 with 32 bit offsets +data is addressed relative to a4 with 32 bit offsets resident Target Common Report Var(flag_pic,3) -data is adressed relativ to a4, linked as resident +data is addressed relative to a4, linked as resident resident32 Target Common Report Var(flag_pic,4) -data is adressed relativ to a4 with 32 bit offsets, linked as resident +data is addressed relative to a4 with 32 bit offsets, linked as resident mcrt= Target RejectNegative Var(amigaos_crt) Joined Specify startup binary fbbb= -Target Var(flag_bbb_opts) Joined -Enable Bebbo's optimizations +Target RejectNegative Report Var(string_bbb_opts) Joined +-fbbb=\t\tEnable Bebbo's optimizations. Default: -fbbb=+\n valid letters:\n\t\t+\t\tenable all\n\t\t-\t\tdisable all\n\t\ta\t\tadd move optimization\n\t\tc\t\tcompare to sub\n\t\te\t\teliminate dead assignments\n\t\tf\t\tshrink stack frame\n\t\tm\t\tmerge add statements\n\t\tp\t\tpropagate move pairs from loops\n\t\tr\t\tadditional reg rename pass\n\t\tv\t\tbe verbose\n\t\tx or X\t\tdump insns From 5abbd0e25e9cc50d4449884567079df90141511b Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 14 Apr 2017 18:34:31 +0200 Subject: [PATCH 067/303] @B resolv issues to get everything built --- gcc/bbb-opts.c | 255 +++++++++++++++++++-------------------------------------- gcc/final.c | 2 +- gcc/passes.def | 6 +- 3 files changed, 89 insertions(+), 174 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 56251b906184..1b1863e9ae8f 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -51,6 +51,42 @@ #include #include +static bool be_verbose; + +extern struct lang_hooks lang_hooks; +extern tree current_function_decl; +static tree last_function_decl; +static char const * +getCurrentFunctionName () +{ + static char fxname[512]; + if (current_function_decl == NULL) + strcpy (fxname, ""); + else + strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2)); + return fxname; +} + +static int +log (char const * fmt, ...) +{ + if (!be_verbose) + return 0; + + va_list args; + va_start(args, fmt); + if (last_function_decl != current_function_decl) + { + last_function_decl = current_function_decl; + printf (":bbb: in '%s'\n", getCurrentFunctionName ()); + } + printf (":bbb: "); + int retval = vprintf (fmt, args); + va_end(args); + fflush (stdout); + return retval; +} + /* Enough for m68k. * Why a class? Maybe extend it for general usage. * @@ -231,21 +267,6 @@ do_reg_rename (rtx x, unsigned oldregno, unsigned newregno) } } -static int -bit2regno (unsigned bit) -{ - if (!bit) - return -1; - - unsigned regno = 0; - while (!(bit & 1)) - { - ++regno; - bit >>= 1; - } - return regno; -} - /* * Collect some data. */ @@ -358,19 +379,6 @@ update_insns () } } -extern struct lang_hooks lang_hooks; -extern tree current_function_decl; -static char const * -getCurrentFunctionName () -{ - static char fxname[512]; - if (current_function_decl == NULL) - strcpy (fxname, ""); - else - strcpy (fxname, lang_hooks.decl_printable_name (current_function_decl, 2)); - return fxname; -} - static void update_insn_infos (void) { @@ -432,7 +440,7 @@ update_insn_infos (void) rtx op, reg; if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) - for (int r = REGNO(reg); r <= END_REGNO (reg); ++r) + for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) use.use (r); } @@ -468,7 +476,7 @@ update_insn_infos (void) if (ANY_RETURN_P(pattern)) { ii.reset (); - ii.use (0); +// ii.use (0); } else { @@ -494,7 +502,7 @@ update_insn_infos (void) continue; } - if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER) + if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER && be_verbose) { fprintf (stderr, "##### "); debug_rtx (insn); @@ -761,9 +769,9 @@ propagate_moves () rtx_insn * after = insns[index + 1]; rtx bset = single_set (before); - fprintf (stderr, ":bbb: propagate_moves condition met, moving regs %s, %s\n", + log ("propagate_moves condition met, moving regs %s, %s\n", reg_names[REGNO(srci)], - reg_names[REGNO(dsti)]); + reg_names[REGNO(dsti)]); /* Move in front of loop and mark as dead. */ rtx_insn * newii = make_insn_raw (PATTERN (ii)); @@ -800,7 +808,7 @@ propagate_moves () /* add fixes if there were jumps out of the loop. */ if (jump_out.size ()) { - fprintf (stderr, ":bbb: propagate_moves fixing %d jump outs\n", jump_out.size ()); + log ("propagate_moves fixing %d jump outs\n", jump_out.size ()); for (unsigned k = 0; k < jump_out.size (); ++k) { @@ -873,7 +881,8 @@ opt_strcpy () rtx dst = XEXP(src, 0); src = XEXP(src, 1); - if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst)) +// if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst)) + if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead(REGNO(dst), index)) { /* now check via NOTICE_UPDATE_CC*/ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x); @@ -889,10 +898,8 @@ opt_strcpy () { rtx link; - fprintf ( - stderr, - ":bbb: opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", - reg_names[REGNO(dst)]); + log ("opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", + reg_names[REGNO(dst)]); SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); @@ -1017,7 +1024,7 @@ commute_add_move (void) if (validate_change (next, &SET_DEST(set2), newmem, 0)) { - fprintf (stderr, ":bbb: commute_add_move found\n"); + log ("commute_add_move found\n"); SET_INSN_DELETED(insn); @@ -1130,7 +1137,7 @@ const_cmp_to_sub (void) SET_INSN_DELETED(prev); prev = emit_insn_before (neuprev, insn); - fprintf (stderr, ":bbb: const_cmp_to_sub replaced reg-reg compare with sub\n"); + log ("const_cmp_to_sub replaced reg-reg compare with sub\n"); if (dstp != left) { @@ -1191,7 +1198,7 @@ const_cmp_to_sub (void) if (code != newcode) { - fprintf (stderr, ":bbb: patch jcc %d -> %d\n", code, newcode); + log ("patch jcc %d -> %d\n", code, newcode); XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1)); } } @@ -1225,7 +1232,7 @@ elim_dead_assign (void) if (is_reg_dead (REGNO(dst), index)) { - fprintf (stderr, ":bbb: elim_dead_assign to %s\n", reg_names[REGNO(dst)]); + log ("elim_dead_assign to %s\n", reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); ++change_count; } @@ -1291,13 +1298,15 @@ merge_add (void) if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3)) continue; - fprintf (stderr, ":bbb: merge_add applied\n"); + log ("merge_add applied\n"); + + rtx_insn * newins1 = make_insn_raw(gen_rtx_SET(dst1, l1)); + add_insn_after (newins1, ins1, 0); + SET_INSN_DELETED(ins1); - SET_SRC(set1) = l1; rtx_insn * newins2 = make_insn_raw (PATTERN (ins2)); add_insn_after (newins2, ins3, 0); SET_INSN_DELETED(ins2); - df_insn_rescan (ins1); } return change_count; } @@ -1508,9 +1517,7 @@ shrink_stack_frame (void) { insn_info & jj = infos[i]; ii |= jj; -// fprintf (stderr, "%08lx %08lx\n", jj._use, jj._def); } -// fprintf (stderr, "%08lx %08lx\n", ii._use, ii._def); unsigned freemask = ~ii._use; rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM); @@ -1553,7 +1560,7 @@ shrink_stack_frame (void) unsigned regbit = 1 << REGNO(reg); if (freemask & regbit) { - fprintf (stderr, i < prologueend ? ":bbb: remove push for %s\n" : ":bbb: remove pop for %s\n", + log (i < prologueend ? "remove push for %s\n" : "remove pop for %s\n", reg_names[REGNO(reg)]); if (i < prologueend) adjust += 4; @@ -1574,7 +1581,7 @@ shrink_stack_frame (void) int add1 = i < prologueend || !usea5 ? 1 : 0; if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2) { - fprintf (stderr, ":bbb: shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); + log ("shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); if (regs.size () <= 2) { for (unsigned k = 0; k < regs.size (); ++k) @@ -1667,7 +1674,7 @@ shrink_stack_frame (void) if (freemask & regbit) { adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; - fprintf (stderr, ":bbb: remove push for %s\n", reg_names[REGNO(src)]); + log ("remove push for %s\n", reg_names[REGNO(src)]); SET_INSN_DELETED(insn); } } @@ -1678,7 +1685,7 @@ shrink_stack_frame (void) unsigned regbit = 1 << REGNO(dst); if (freemask & regbit) { - fprintf (stderr, ":bbb: remove pop for %s\n", reg_names[REGNO(dst)]); + log ("remove pop for %s\n", reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); } } @@ -1726,99 +1733,6 @@ shrink_stack_frame (void) return 0; } -/* - * Always prefer lower register numbers within the class. - */ -static unsigned -bb_reg_rename (void) -{ - for (unsigned index = 0; index < insns.size (); ++index) - { - insn_info & ii = infos[index]; - const unsigned def = ii._def; - unsigned mask = ii.get_def_mask (); - - if (!mask) - continue; - - std::vector found; - std::vector todo; - if (index + 1 < insns.size ()) - todo.push_back (index + 1); - - found.push_back (index); - /* a register was defined, follow all branches. */ - while (todo.size ()) - { - unsigned pos = todo[todo.size () - 1]; - todo.pop_back (); - - if (LABEL_P(insns[pos])) - { - if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); - continue; - } - - insn_info & jj = infos[pos]; - - /* update free regs. */ - mask &= ~jj._use; - mask &= ~jj._def; - if (!mask) - break; - - /* defined again. */ - if (jj._def & def) - continue; - - /* not referenced. */ - if (!(jj._use & def)) - continue; - - found.push_back (pos); - - /* follow jump and/or next insn. */ - rtx_insn * insn = insns[pos]; - if (JUMP_P(insn)) - { - std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); - if (j != insn2index.end ()) - todo.push_back (j->second); - - rtx jmppattern = PATTERN (insn); - - rtx jmpsrc = XEXP(jmppattern, 1); - if (GET_CODE(jmpsrc) == IF_THEN_ELSE) - if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); - } - else if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); - } - - if (mask) - { - int oldregno = bit2regno (def); - int newregno = bit2regno (mask); - fprintf (stderr, ":bbb: bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], - found.size ()); - - for (std::vector::iterator i = found.begin (); i != found.end (); ++i) - { - debug_rtx (insns[*i]); - do_reg_rename (PATTERN (insns[*i]), oldregno, newregno); - } - - cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); - cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); - return 1; - } - } - return 0; -} - -extern const char * current_function_func_begin_label; extern class opt_pass * global_pass_regrename; namespace @@ -1848,10 +1762,10 @@ namespace virtual bool gate (function *) { - if (!flag_bbb_opts) - flag_bbb_opts = "*"; + if (!string_bbb_opts) + string_bbb_opts = "+"; - return TARGET_AMIGA && optimize > 0 && flag_bbb_opts; + return TARGET_AMIGA && optimize > 0 && string_bbb_opts && !strchr (string_bbb_opts, '-'); } virtual unsigned int @@ -1883,20 +1797,21 @@ namespace df_note_add_problem (); df_analyze (); - update_insns (); + be_verbose = strchr (string_bbb_opts, 'v'); - bool do_opt_strcpy = strchr (flag_bbb_opts, 's') || strchr (flag_bbb_opts, '*'); - bool do_commute_add_move = strchr (flag_bbb_opts, 'a') || strchr (flag_bbb_opts, '*'); - bool do_propagate_moves = strchr (flag_bbb_opts, 'p') || strchr (flag_bbb_opts, '*'); - bool do_const_cmp_to_sub = strchr (flag_bbb_opts, 'c') || strchr (flag_bbb_opts, '*'); - bool do_merge_add = strchr (flag_bbb_opts, 'm') || strchr (flag_bbb_opts, '*'); - bool do_elim_dead_assign = strchr (flag_bbb_opts, 'e') || strchr (flag_bbb_opts, '*'); - bool do_bb_reg_rename = strchr (flag_bbb_opts, 'r') || strchr (flag_bbb_opts, '*'); - bool do_shrink_stack_frame = strchr (flag_bbb_opts, 'f') || strchr (flag_bbb_opts, '*'); + bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); + bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); + bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+'); + bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+'); + bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+'); + bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+'); + bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); + bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); for (;;) { int done = 1; + update_insns (); if (do_opt_strcpy && opt_strcpy ()) done = 0, update_insns (); @@ -1916,20 +1831,20 @@ namespace if (do_elim_dead_assign && elim_dead_assign ()) done = 0, update_insns (); - if (done) - break; - } + if (do_bb_reg_rename && ::global_pass_regrename) + { + class opt_pass * rr = ::global_pass_regrename->clone (); + rr->execute (0); - if (do_bb_reg_rename && ::global_pass_regrename) - { - class opt_pass * rr = ::global_pass_regrename->clone (); - rr->execute (0); + // update_insns (); + // update_insn_infos (); + // bb_reg_rename (); -// update_insns (); -// update_insn_infos (); -// bb_reg_rename (); + update_insns (); + } - update_insns (); + if (done) + break; } if (do_shrink_stack_frame) @@ -1938,8 +1853,8 @@ namespace update_insns (); } - if (strchr (flag_bbb_opts, 'X') || strchr (flag_bbb_opts, 'x')) - dump_insns ("bbb 1", strchr (flag_bbb_opts, 'X')); + if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) + dump_insns ("bbb", strchr (string_bbb_opts, 'X')); clear (); return 0; diff --git a/gcc/final.c b/gcc/final.c index 9d21ffc1baff..31f9b4815d75 100644 --- gcc/final.c +++ gcc/final.c @@ -2165,7 +2165,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, /* Ignore deleted insns. These can occur when we split insns (due to a template of "#") while not optimizing. */ - if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED) + if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED || GET_CODE(insn) == DEBUG_IMPLICIT_PTR) return NEXT_INSN (insn); switch (GET_CODE (insn)) diff --git a/gcc/passes.def b/gcc/passes.def index 5b78cbd7fb38..f48fd2581cba 100644 --- gcc/passes.def +++ gcc/passes.def @@ -447,6 +447,9 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_ree); NEXT_PASS (pass_compare_elim_after_reload); NEXT_PASS (pass_branch_target_load_optimize1); + NEXT_PASS (pass_thread_prologue_and_epilogue); + NEXT_PASS (pass_rtl_dse2); + NEXT_PASS (pass_stack_adjustments); NEXT_PASS (pass_jump2); NEXT_PASS (pass_duplicate_computed_gotos); NEXT_PASS (pass_sched_fusion); @@ -454,9 +457,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_if_after_reload); NEXT_PASS (pass_regrename); NEXT_PASS (pass_cprop_hardreg); - NEXT_PASS (pass_thread_prologue_and_epilogue); - NEXT_PASS (pass_rtl_dse2); - NEXT_PASS (pass_stack_adjustments); NEXT_PASS (pass_fast_rtl_dce); NEXT_PASS (pass_reorder_blocks); NEXT_PASS (pass_bbb_optimizations); From 7c3f103835a555944b28e4e2a0726f33830abc6a Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 14 Apr 2017 18:35:14 +0200 Subject: [PATCH 068/303] @N add eclipse project files --- .cproject | 180 +++++++++++++++++++++++++++++ .project | 16 +++ .settings/language.settings.xml | 25 ++++ .settings/org.eclipse.cdt.codan.core.prefs | 71 ++++++++++++ .settings/org.eclipse.cdt.core.prefs | 6 + .settings/org.eclipse.core.runtime.prefs | 5 + 6 files changed, 303 insertions(+) create mode 100755 .cproject create mode 100755 .settings/language.settings.xml create mode 100755 .settings/org.eclipse.cdt.codan.core.prefs create mode 100755 .settings/org.eclipse.cdt.core.prefs create mode 100755 .settings/org.eclipse.core.runtime.prefs diff --git a/.cproject b/.cproject new file mode 100755 index 000000000000..62b1c0f38dcb --- /dev/null +++ .cproject @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project index ab5c4b198d08..22b8c5a11f48 100644 --- .project +++ .project @@ -5,7 +5,23 @@ + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml new file mode 100755 index 000000000000..c6ac9211311a --- /dev/null +++ .settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100755 index 000000000000..b5248c620107 --- /dev/null +++ .settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,71 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside=-Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment=-Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 000000000000..8ec9fe72ca59 --- /dev/null +++ .settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/PATH/value=C\:\\WINDOWS\\system32;C\:\\WINDOWS;C\:\\Program Files\\SlikSvn\\bin;C\:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;c\:\\cygwin\\bin;D\:\\develop\\workspaces\\c1\\amigaos-cross-toolchain\\m68k-amigaos\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.452878522/appendContributed=true diff --git a/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs new file mode 100755 index 000000000000..12511e62a174 --- /dev/null +++ .settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,5 @@ +content-types/enabled=true +content-types/org.eclipse.cdt.core.cHeader/file-extensions=def +content-types/org.eclipse.cdt.core.cxxHeader/file-extensions=h +content-types/org.eclipse.cdt.core.cxxSource/file-extensions=c +eclipse.preferences.version=1 From 4920a3ed01948bcc777d84e3c42f4e92310ee499 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 19 Apr 2017 13:38:11 +0200 Subject: [PATCH 069/303] @R be nice to other windows programs and replace /cygdrive/x/ with x:/ -> include/lib path discovery is now working in Eclipse running on Windows --- gcc/gcc.c | 8 ++++---- libiberty/lrealpath.c | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/gcc/gcc.c b/gcc/gcc.c index 33ca41545736..2974b91300ca 100644 --- gcc/gcc.c +++ gcc/gcc.c @@ -10109,7 +10109,7 @@ const char * amiga_m68k_prefix_func(int argc, const char ** argv) { char * p = 0; if (standard_libexec_prefix) { - char * glp = concat(standard_libexec_prefix, "",0); + char * glp = concat(standard_libexec_prefix, "", NULL); p = strrchr(glp, '/'); if (p) { @@ -10122,17 +10122,17 @@ const char * amiga_m68k_prefix_func(int argc, const char ** argv) { if (p) { p[1] = 0; - p = concat(glp, "m68k-amigaos/", 0); + p = concat(glp, "m68k-amigaos/", NULL); } } } free(glp); } if (!p) - p = concat("../../../../", "", 0); + p = concat("../../../../", "", NULL); for (int i = 0; i < argc; ++i) { - char * q = concat(p, argv[i], 0); + char * q = concat(p, argv[i], NULL); free(p); p = q; } diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c index b27c8de990e9..78c06e46da58 100644 --- libiberty/lrealpath.c +++ libiberty/lrealpath.c @@ -73,7 +73,7 @@ extern char *canonicalize_file_name (const char *); #endif char * -lrealpath (const char *filename) +__xlrealpath (const char *filename) { /* Method 1: The system has a compile time upper bound on a filename path. Use that and realpath() to canonicalize the name. This is @@ -155,3 +155,19 @@ lrealpath (const char *filename) /* This system is a lost cause, just duplicate the filename. */ return strdup (filename); } + + +char * +lrealpath (const char *filename) +{ + char * r = __xlrealpath(filename); +#if defined (_WIN32) + if (strncmp(r, "/cygdrive/", 10) == 0) + { + r[9] = r[10]; + r[10] = ':'; + r = strdup(&r[9]); + } +#endif + return r; +} From f6379a10611d6376109a63b65768387905a30490 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 19 Apr 2017 13:41:44 +0200 Subject: [PATCH 070/303] @B fix rename-registers if using register parameters: add clobbers for the regs --- gcc/config/m68k/amigaos.c | 1671 +++++++++++++++++++++++---------------------- gcc/config/m68k/m68k.c | 6 + 2 files changed, 842 insertions(+), 835 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 88205e25476e..ca8eea305345 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -1,835 +1,836 @@ -/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 - Free Software Foundation, Inc. - Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). - Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). - -This file is part of GCC. - -GCC 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. - -GCC 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 GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -//work without flag_writable_strings which is not in GCC4 -#define REGPARMS_68K 1 - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "output.h" -#include "tree.h" -#include "attribs.h" -#include "flags.h" -#include "expr.h" -#include "toplev.h" -#include "tm_p.h" -#include "target.h" -#include "diagnostic-core.h" -#include "config/m68k/amigaos.h" - -//#define MYDEBUG 1 -#ifdef MYDEBUG -#define DPRINTF(x) printf x; fflush(stdout); -#else -#define DPRINTF(x) -#endif - -//int amiga_declare_object; - -#if 0 -static int amigaos_put_in_text (tree); -static rtx gen_stack_management_call (rtx, rtx, const char *); - -/* Baserel support. */ - -/* Does operand (which is a symbolic_operand) live in text space? If - so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. - - This function is used in base relative code generation. */ - -int -read_only_operand (rtx operand) -{ - if (GET_CODE (operand) == CONST) - operand = XEXP (XEXP (operand, 0), 0); - if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); - return 1; -} - -/* Choose the section to use for DECL. RELOC is true if its value contains - any relocatable expression. */ - -void -amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED, - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) -{ - // if (TREE_CODE (decl) == STRING_CST) -// { -//// flag_writable_strings /data_section not in gcc4, -////make life easy and put to same section -//// if (! flag_writable_strings) -//// readonly_data_section (); -//// else -// //data_section (); -// } -// else if (TREE_CODE (decl) == VAR_DECL) -// { -// if (TREE_READONLY (decl) -// && ! TREE_THIS_VOLATILE (decl) -// && DECL_INITIAL (decl) -// && (DECL_INITIAL (decl) == error_mark_node -// || TREE_CONSTANT (DECL_INITIAL (decl))) -// && (!flag_pic || (flag_pic<3 && !reloc) -// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))) -// readonly_data_section (); -// else -// data_section (); -// } -// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl) -// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))) -// readonly_data_section (); -// else - //data_section (); -} - -/* This function is used while generating a base relative code. - It returns 1 if a decl is not relocatable, i. e., if it can be put - in the text section. - Currently, it's very primitive: it just checks if the object size - is less than 4 bytes (i. e., if it can hold a pointer). It also - supports arrays and floating point types. */ - -static int -amigaos_put_in_text (tree decl) -{ - tree type = TREE_TYPE (decl); - if (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); - return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0 - && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32) - || FLOAT_TYPE_P (type); -} - -/* Record properties of a DECL into the associated SYMBOL_REF. */ - -void -amigaos_encode_section_info (tree decl, rtx rtl, int first) -{ - default_encode_section_info (decl, rtl, first); - - - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - else - { - if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl) - && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST - ) - || amigaos_put_in_text (decl))) - || (TREE_CODE (decl) == VAR_DECL - && DECL_SECTION_NAME (decl) != NULL)) - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - } -} - -/* Common routine used to check if a4 should be preserved/restored. */ - -int -amigaos_restore_a4 (void) -{ - return (flag_pic >= 3 && - (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4 - || lookup_attribute ("saveds", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))); -} - -void -amigaos_alternate_pic_setup (FILE *stream) -{ - if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) - asm_fprintf (stream, "\tjbsr %U__restore_a4\n"); - else if (lookup_attribute ("saveds", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n"); -} - -/* Attributes support. */ - -#define AMIGA_CHIP_SECTION_NAME ".datachip" - -/* Handle a "chip" attribute; - arguments as in struct attribute_spec.handler. */ - -tree -amigaos_handle_decl_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - if (TREE_CODE (*node) == VAR_DECL) - { - if (is_attribute_p ("chip", name)) -#ifdef TARGET_ASM_NAMED_SECTION - { - if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node)) - error ("`chip' attribute cannot be specified for local variables"); - else - { - /* The decl may have already been given a section attribute from - a previous declaration. Ensure they match. */ - if (DECL_SECTION_NAME (*node) == NULL_TREE) - DECL_SECTION_NAME (*node) = - build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1, - AMIGA_CHIP_SECTION_NAME); - else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)), - AMIGA_CHIP_SECTION_NAME) != 0) - { - error_with_decl (*node, - "`chip' for `%s' conflicts with previous declaration"); - } - } - } -#else - error ("`chip' attribute is not supported for this target"); -#endif - } - else - { - warning (OPT_Wattributes, "`%s' attribute only applies to variables", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -//----- from 68k.c start - - - - - - -/* Stack checking and automatic extension support. */ - -void -amigaos_prologue_begin_hook (FILE *stream, int fsize) -{ - if (TARGET_STACKCHECK) - { - if (fsize < 256) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tjra %U__stkovf\n" - "\t0:\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit"))); - else - asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n", - fsize); - } -} - -void -amigaos_alternate_frame_setup_f (FILE *stream, int fsize) -{ - if (fsize < 128) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I%d,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\tlink %Ra5,%I%d:W\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit")), - fsize, -fsize); - else - asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n", - fsize); -} - -void -amigaos_alternate_frame_setup (FILE *stream, int fsize) -{ - if (!fsize) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I0,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit"))); - else if (fsize < 128) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I%d,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\taddw %I%d,%Rsp\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit")), - fsize, -fsize); - else - asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n", - fsize); -} - -//static rtx -//gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func) -//{ -// rtx call_insn, call, seq, name; -// start_sequence (); -// -// /* Move arg to d0. */ -// emit_move_insn (gen_rtx_REG (SImode, 0), arg); -// -// /* Generate the function reference. */ -// name = gen_rtx_SYMBOL_REF (Pmode, func); -// SYMBOL_REF_FLAG (name) = 1; -// /* If optimizing, put it in a psedo so that several loads can be merged -// into one. */ -// if (optimize && ! flag_no_function_cse) -// name = copy_to_reg (name); -// -// /* Generate the function call. */ -// call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (FUNCTION_MODE, name), -// const0_rtx); -// /* If we are doing stack extension, notify about the sp change. */ -// if (stack_pointer) -// call = gen_rtx_SET (VOIDmode, stack_pointer, call); -// -// /* Generate the call instruction. */ -// call_insn = emit_call_insn (call); -// /* Stack extension does not change memory in an unpredictable way. */ -// RTL_CONST_OR_PURE_CALL_P (call_insn) = 1; -// /* We pass an argument in d0. */ -// CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (VOIDmode, -// gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 0)), 0); -// -// seq = get_insns (); -// end_sequence (); -// return seq; -//} -// -//rtx -//gen_stack_cleanup_call (rtx stack_pointer, rtx sa) -//{ -// return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp"); -//} -// -//void -//amigaos_alternate_allocate_stack (rtx *operands) -//{ -// if (TARGET_STACKEXTEND) -// emit_insn (gen_stack_management_call (stack_pointer_rtx, operands[1], -// "__sub_d0_sp")); -// else -// { -// if (TARGET_STACKCHECK) -// emit_insn (gen_stack_management_call (0, operands[1], "__stkchk_d0")); -// anti_adjust_stack (operands[1]); -// } -// emit_move_insn (operands[0], virtual_stack_dynamic_rtx); -//} -#endif - -/* - * begin-GG-local: explicit register specification for parameters. - * - * Reworked and ported to gcc-6.2.0 by Stefan "Bebbo" Franke. - */ - -/** - * Define this here and add it to tm_p -> all know the custom type and allocate/use the correct size. - */ -struct amigaos_args -{ - int num_of_regs; - long regs_already_used; - int last_arg_reg; - int last_arg_len; - tree formal_type; /* New field: formal type of the current argument. */ -}; - -static struct amigaos_args mycum; -static CUMULATIVE_ARGS * lastcum; - -/* Argument-passing support functions. */ - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -void -amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) -{ - struct amigaos_args * cum = &mycum; - lastcum = cump; - cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; - DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); - - /* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - - cum->last_arg_reg = -1; - cum->regs_already_used = 0; - - if (decl) - { - tree attrs = DECL_ATTRIBUTES(decl); - if (lookup_attribute ("stkparm", attrs)) - cum->num_of_regs = 0; - else - { - tree ratree = lookup_attribute ("regparm", attrs); - cum->num_of_regs = amigaos_regparm != 0 ? - amigaos_regparm : AMIGAOS_DEFAULT_REGPARM; - if (ratree) - { - tree args = TREE_VALUE(ratree); - - if (args && TREE_CODE (args) == TREE_LIST) - { - tree val = TREE_VALUE(args); - if (TREE_CODE (val) == INTEGER_CST) - { - int no = TREE_INT_CST_LOW(val); - if (no > 0 && no < AMIGAOS_MAX_REGPARM) - cum->num_of_regs = no; - } - } - } - } - } - else - /* Libcall. */ - cum->num_of_regs = 0; - - if (cum->num_of_regs) - { - /* If this is a vararg call, put all arguments on stack. */ - tree param, next_param; - for (param = TYPE_ARG_TYPES(fntype); param; param = next_param) - { - next_param = TREE_CHAIN(param); - if (!next_param && TREE_VALUE (param) != void_type_node) - cum->num_of_regs = 0; - } - } - - //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM) - // /* If return value is a structure, and we pass the buffer address in a - // register, we can't use this register for our own purposes. - // FIXME: Something similar would be useful for static chain. */ - // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) - // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM); - //#endif - - if (fntype) - cum->formal_type = TYPE_ARG_TYPES(fntype); - else - /* Call to compiler-support function. */ - cum->formal_type = 0; - DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); -} - -/* Update the data in CUM to advance over an argument. */ - -void -amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, - bool) -{ - struct amigaos_args * cum = &mycum; - CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v); - /* Update the data in CUM to advance over an argument. */ - - DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump)); - if (cump != lastcum) - return; - - if (cum->last_arg_reg != -1) - { - int count; - for (count = 0; count < cum->last_arg_len; count++) - cum->regs_already_used |= (1 << (cum->last_arg_reg + count)); - cum->last_arg_reg = -1; - } - - if (cum->formal_type) - cum->formal_type = TREE_CHAIN(cum->formal_type); -} - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. */ - -static struct rtx_def * -_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree); - -static struct rtx_def * -_m68k_function_arg (CUMULATIVE_ARGS *cump, machine_mode mode, const_tree type) -{ - struct amigaos_args * cum = &mycum; - DPRINTF(("m68k_function_arg numOfRegs=%d\r\n", cum ? cum->num_of_regs : 0)); - - if (cump != lastcum) - return 0; - - if (cum->num_of_regs) - { - int regbegin = -1, altregbegin = -1, len; - - /* FIXME: The last condition below is a workaround for a bug. */ - if (TARGET_68881 && FLOAT_MODE_P(mode) && - GET_MODE_UNIT_SIZE (mode) <= 12 - && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode)) - { - regbegin = 16; /* FPx */ - len = GET_MODE_NUNITS(mode); - } - /* FIXME: Two last conditions below are workarounds for bugs. */ - else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode) - { - if (!type || POINTER_TYPE_P(type)) - regbegin = 8; /* Ax */ - else - regbegin = 0; /* Dx */ - altregbegin = 8 - regbegin; - len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; - } - - if (regbegin != -1) - { - int reg; - long mask; - - look_for_reg: mask = 1 << regbegin; - for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1) - if (!(cum->regs_already_used & mask)) - { - int end; - for (end = reg; end < cum->num_of_regs && end < reg + len; - end++, mask <<= 1) - if (cum->regs_already_used & mask) - break; - if (end == reg + len) - { - cum->last_arg_reg = reg + regbegin; - cum->last_arg_len = len; - break; - } - } - - if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) - { - DPRINTF(("look for alt reg\n")); - regbegin = altregbegin; - altregbegin = -1; - goto look_for_reg; - } - } - - if (cum->last_arg_reg != -1) - { - DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg)); - return gen_rtx_REG (mode, cum->last_arg_reg); - } - } - return 0; -} - -/* A C expression that controls whether a function argument is passed - in a register, and which register. */ - -struct rtx_def * -amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, - const_tree type, bool) -{ - struct amigaos_args * cum = &mycum; - - DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p)); - - CUMULATIVE_ARGS *cump = (CUMULATIVE_ARGS *) get_cumulative_args (cum_v); - - if (cump != lastcum) - return 0; - - tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE; - if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) - { - int i; - cum->last_arg_reg = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low; - cum->last_arg_len = HARD_REGNO_NREGS(cum->last_arg_reg, mode); - - for (i = 0; i < cum->last_arg_len; i++) - if (cum->regs_already_used & (1 << (cum->last_arg_reg + i))) - { - error ("two parameters allocated for one register"); - break; - } - return gen_rtx_REG (mode, cum->last_arg_reg); - } - return _m68k_function_arg (cump, mode, type); -} - -/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, - one if they are compatible, and two if they are nearly compatible - (which causes a warning to be generated). */ - -int -amigaos_comp_type_attributes (const_tree type1, const_tree type2) -{ - DPRINTF(("amigaos_comp_type_attributes\n")); - /* Functions or methods are incompatible if they specify mutually exclusive - ways of passing arguments. */ - if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE) - { - tree arg1, arg2; - arg1 = TYPE_ARG_TYPES(type1); - arg2 = TYPE_ARG_TYPES(type2); - for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2)) - { - tree attr1 = TYPE_ATTRIBUTES(arg1); - tree attr2 = TYPE_ATTRIBUTES(arg2); - if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1)))) - attr1 = NULL_TREE; - if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2)))) - attr2 = NULL_TREE; - if (attr1 && attr2) - { - if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low - != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low) - return 0; - } - else if (attr1 || attr2) - return 0; /* asm attribute only on one side. */ - } - if (arg1 || arg2) - return 0; /* different count of parameters. */ - } - return 1; -} - -/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, - one if they are compatible, and two if they are nearly compatible - (which causes a warning to be generated). */ -#if 0 -static int -m68k_comp_type_attributes (tree type1, tree type2) -{ - - /* Functions or methods are incompatible if they specify mutually - exclusive ways of passing arguments. */ - if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) - { - tree arg1, arg2; - if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != - !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) - || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != - !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) - return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */ - - arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); - arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); - if (arg1 && arg2) - { - int num1 = 0, num2 = 0; - if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) - { - tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); - if (numofregs) - num1 = TREE_INT_CST_LOW (numofregs); - } - if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) - { - tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); - if (numofregs) - num2 = TREE_INT_CST_LOW (numofregs); - } - if (num1 != num2) - return 0; /* Different numbers, or no number in one type. */ - } - } -#ifdef TARGET_AMIGAOS - return amigaos_comp_type_attributes(type1, type2); -#else - return 1; -#endif -} -#endif - -/* end-GG-local */ - - -/* Handle a "regparm", "stkparm" attribute; - arguments as in struct attribute_spec.handler. */ -tree -amigaos_handle_type_attribute (tree *node, tree name, tree args, - int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) -{ - tree nnn = *node; - do { // while (0); - DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn))); - if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE - || TREE_CODE (nnn) == METHOD_TYPE) - { - /* 'regparm' accepts one optional argument - number of registers in - single class that should be used to pass arguments. */ - if (is_attribute_p ("regparm", name)) - { - DPRINTF(("regparm found\n")); - - if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn))) - { - error ("`regparm' and `stkparm' are mutually exclusive"); - break; - } - if (args && TREE_CODE (args) == TREE_LIST) - { - tree val = TREE_VALUE(args); - DPRINTF(("regparm with val: %d\n", TREE_CODE(val))); - if (TREE_CODE (val) == INTEGER_CST) - { - int no = TREE_INT_CST_LOW(val); - if (no < 0 || no > AMIGAOS_MAX_REGPARM) - { - error ("`regparm' attribute: value %d not in [0 - %d]", - no, - AMIGAOS_MAX_REGPARM); - break; - } - } - else - { - error ("invalid argument(s) to `regparm' attribute"); - break; - } - } - } - else if (is_attribute_p ("stkparm", name)) - { - if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn))) - { - error ("`regparm' and `stkparm' are mutually exclusive"); - break; - } - } - else if (is_attribute_p ("stackext", name)) - { - if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn))) - { - error ("`stackext' and `interrupt' are mutually exclusive"); - break; - } - } - else if (is_attribute_p ("saveds", name)) - { - } - } - else - { - warning (OPT_Wattributes, "`%s' attribute only applies to functions", - IDENTIFIER_POINTER(name)); - } - return NULL_TREE; - } while (0); - // error case - *no_add_attrs = true; - return NULL_TREE; -} - - -extern bool -m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); - -bool -amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, - int *total, bool speed) -{ -// DPRINTF(("outer: %d, opno: %d", outer_code, opno)); - bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); -// *total *= 4; -// fprintf(stderr, "costs: %d, mode=%d, outer=%d, opno=%d, speed=%d, ok=%d\n", *total * 4, mode, outer_code, opno, speed, r); -// debug_rtx(x); - return r; -} - - -/* Output assembly to switch to section NAME with attribute FLAGS. */ - -extern void -amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) -{ - if (0 == strncmp(".text", name, 5)) - name = ".text"; - fprintf (asm_out_file, "\t%s\n", name); -} - -/* Baserel support. */ - -/** - * Does x reference the pic_reg and is const or plus? - */ -int amiga_is_const_pic_ref(const_rtx x) -{ - const_rtx y = x; - if (flag_pic < 3) - return false; - while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS) - y = XEXP(y, 0); - return (x != y && REG_P(y) && REGNO(y) == PIC_REG); -} - - -/* Does operand (which is a symbolic_operand) live in text space? If - so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. - - This function is used in base relative code generation. */ - -int -read_only_operand (rtx operand) -{ - if (GET_CODE (operand) == CONST) - operand = XEXP (XEXP (operand, 0), 0); - if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); - return 1; -} - -reg_class_t -amiga_preferred_rename_class2(reg_class_t rclass ATTRIBUTE_UNUSED, int regno ) -{ - if (regno == 0) - return D0_REGS; - if (regno == 8) - return A0_REGS; - return regno_reg_class[regno]; -} +/* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 + Free Software Foundation, Inc. + Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). + Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). + +This file is part of GCC. + +GCC 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. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +//work without flag_writable_strings which is not in GCC4 +#define REGPARMS_68K 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "output.h" +#include "tree.h" +#include "attribs.h" +#include "flags.h" +#include "expr.h" +#include "toplev.h" +#include "tm_p.h" +#include "target.h" +#include "diagnostic-core.h" +#include "config/m68k/amigaos.h" + +//#define MYDEBUG 1 +#ifdef MYDEBUG +#define DPRINTF(x) printf x; fflush(stdout); +#else +#define DPRINTF(x) +#endif + +//int amiga_declare_object; + +#if 0 +static int amigaos_put_in_text (tree); +static rtx gen_stack_management_call (rtx, rtx, const char *); + +/* Baserel support. */ + +/* Does operand (which is a symbolic_operand) live in text space? If + so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. + + This function is used in base relative code generation. */ + +int +read_only_operand (rtx operand) +{ + if (GET_CODE (operand) == CONST) + operand = XEXP (XEXP (operand, 0), 0); + if (GET_CODE (operand) == SYMBOL_REF) + return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + return 1; +} + +/* Choose the section to use for DECL. RELOC is true if its value contains + any relocatable expression. */ + +void +amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) +{ + // if (TREE_CODE (decl) == STRING_CST) +// { +//// flag_writable_strings /data_section not in gcc4, +////make life easy and put to same section +//// if (! flag_writable_strings) +//// readonly_data_section (); +//// else +// //data_section (); +// } +// else if (TREE_CODE (decl) == VAR_DECL) +// { +// if (TREE_READONLY (decl) +// && ! TREE_THIS_VOLATILE (decl) +// && DECL_INITIAL (decl) +// && (DECL_INITIAL (decl) == error_mark_node +// || TREE_CONSTANT (DECL_INITIAL (decl))) +// && (!flag_pic || (flag_pic<3 && !reloc) +// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))) +// readonly_data_section (); +// else +// data_section (); +// } +// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl) +// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))) +// readonly_data_section (); +// else + //data_section (); +} + +/* This function is used while generating a base relative code. + It returns 1 if a decl is not relocatable, i. e., if it can be put + in the text section. + Currently, it's very primitive: it just checks if the object size + is less than 4 bytes (i. e., if it can hold a pointer). It also + supports arrays and floating point types. */ + +static int +amigaos_put_in_text (tree decl) +{ + tree type = TREE_TYPE (decl); + if (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0 + && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32) + || FLOAT_TYPE_P (type); +} + +/* Record properties of a DECL into the associated SYMBOL_REF. */ + +void +amigaos_encode_section_info (tree decl, rtx rtl, int first) +{ + default_encode_section_info (decl, rtl, first); + + + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + else + { + if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl) + && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST + ) + || amigaos_put_in_text (decl))) + || (TREE_CODE (decl) == VAR_DECL + && DECL_SECTION_NAME (decl) != NULL)) + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + } +} + +/* Common routine used to check if a4 should be preserved/restored. */ + +int +amigaos_restore_a4 (void) +{ + return (flag_pic >= 3 && + (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4 + || lookup_attribute ("saveds", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))); +} + +void +amigaos_alternate_pic_setup (FILE *stream) +{ + if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) + asm_fprintf (stream, "\tjbsr %U__restore_a4\n"); + else if (lookup_attribute ("saveds", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n"); +} + +/* Attributes support. */ + +#define AMIGA_CHIP_SECTION_NAME ".datachip" + +/* Handle a "chip" attribute; + arguments as in struct attribute_spec.handler. */ + +tree +amigaos_handle_decl_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == VAR_DECL) + { + if (is_attribute_p ("chip", name)) +#ifdef TARGET_ASM_NAMED_SECTION + { + if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node)) + error ("`chip' attribute cannot be specified for local variables"); + else + { + /* The decl may have already been given a section attribute from + a previous declaration. Ensure they match. */ + if (DECL_SECTION_NAME (*node) == NULL_TREE) + DECL_SECTION_NAME (*node) = + build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1, + AMIGA_CHIP_SECTION_NAME); + else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)), + AMIGA_CHIP_SECTION_NAME) != 0) + { + error_with_decl (*node, + "`chip' for `%s' conflicts with previous declaration"); + } + } + } +#else + error ("`chip' attribute is not supported for this target"); +#endif + } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to variables", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +//----- from 68k.c start + + + + + + +/* Stack checking and automatic extension support. */ + +void +amigaos_prologue_begin_hook (FILE *stream, int fsize) +{ + if (TARGET_STACKCHECK) + { + if (fsize < 256) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tjra %U__stkovf\n" + "\t0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n", + fsize); + } +} + +void +amigaos_alternate_frame_setup_f (FILE *stream, int fsize) +{ + if (fsize < 128) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\tlink %Ra5,%I%d:W\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n", + fsize); +} + +void +amigaos_alternate_frame_setup (FILE *stream, int fsize) +{ + if (!fsize) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I0,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else if (fsize < 128) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\taddw %I%d,%Rsp\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n", + fsize); +} + +//static rtx +//gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func) +//{ +// rtx call_insn, call, seq, name; +// start_sequence (); +// +// /* Move arg to d0. */ +// emit_move_insn (gen_rtx_REG (SImode, 0), arg); +// +// /* Generate the function reference. */ +// name = gen_rtx_SYMBOL_REF (Pmode, func); +// SYMBOL_REF_FLAG (name) = 1; +// /* If optimizing, put it in a psedo so that several loads can be merged +// into one. */ +// if (optimize && ! flag_no_function_cse) +// name = copy_to_reg (name); +// +// /* Generate the function call. */ +// call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (FUNCTION_MODE, name), +// const0_rtx); +// /* If we are doing stack extension, notify about the sp change. */ +// if (stack_pointer) +// call = gen_rtx_SET (VOIDmode, stack_pointer, call); +// +// /* Generate the call instruction. */ +// call_insn = emit_call_insn (call); +// /* Stack extension does not change memory in an unpredictable way. */ +// RTL_CONST_OR_PURE_CALL_P (call_insn) = 1; +// /* We pass an argument in d0. */ +// CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (VOIDmode, +// gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 0)), 0); +// +// seq = get_insns (); +// end_sequence (); +// return seq; +//} +// +//rtx +//gen_stack_cleanup_call (rtx stack_pointer, rtx sa) +//{ +// return gen_stack_management_call (stack_pointer, sa, "__move_d0_sp"); +//} +// +//void +//amigaos_alternate_allocate_stack (rtx *operands) +//{ +// if (TARGET_STACKEXTEND) +// emit_insn (gen_stack_management_call (stack_pointer_rtx, operands[1], +// "__sub_d0_sp")); +// else +// { +// if (TARGET_STACKCHECK) +// emit_insn (gen_stack_management_call (0, operands[1], "__stkchk_d0")); +// anti_adjust_stack (operands[1]); +// } +// emit_move_insn (operands[0], virtual_stack_dynamic_rtx); +//} +#endif + +/* + * begin-GG-local: explicit register specification for parameters. + * + * Reworked and ported to gcc-6.2.0 by Stefan "Bebbo" Franke. + */ + +/** + * Define this here and add it to tm_p -> all know the custom type and allocate/use the correct size. + */ +struct amigaos_args +{ + int num_of_regs; + long regs_already_used; + int last_arg_reg; + int last_arg_len; + tree formal_type; /* New field: formal type of the current argument. */ +}; + +static struct amigaos_args mycum, othercum; + +/* Argument-passing support functions. */ + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +void +amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) +{ + struct amigaos_args * cum = decl == current_function_decl ? &mycum : &othercum; + *cump = (int)cum; + cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; + DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); + + /* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + + cum->last_arg_reg = -1; + cum->regs_already_used = 0; + + if (decl) + { + tree attrs = DECL_ATTRIBUTES(decl); + if (lookup_attribute ("stkparm", attrs)) + cum->num_of_regs = 0; + else + { + tree ratree = lookup_attribute ("regparm", attrs); + cum->num_of_regs = amigaos_regparm != 0 ? + amigaos_regparm : AMIGAOS_DEFAULT_REGPARM; + if (ratree) + { + tree args = TREE_VALUE(ratree); + + if (args && TREE_CODE (args) == TREE_LIST) + { + tree val = TREE_VALUE(args); + if (TREE_CODE (val) == INTEGER_CST) + { + int no = TREE_INT_CST_LOW(val); + if (no > 0 && no < AMIGAOS_MAX_REGPARM) + cum->num_of_regs = no; + } + } + } + } + } + else + /* Libcall. */ + cum->num_of_regs = 0; + + if (cum->num_of_regs) + { + /* If this is a vararg call, put all arguments on stack. */ + tree param, next_param; + for (param = TYPE_ARG_TYPES(fntype); param; param = next_param) + { + next_param = TREE_CHAIN(param); + if (!next_param && TREE_VALUE (param) != void_type_node) + cum->num_of_regs = 0; + } + } + + //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM) + // /* If return value is a structure, and we pass the buffer address in a + // register, we can't use this register for our own purposes. + // FIXME: Something similar would be useful for static chain. */ + // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) + // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM); + //#endif + + if (fntype) + cum->formal_type = TYPE_ARG_TYPES(fntype); + else + /* Call to compiler-support function. */ + cum->formal_type = 0; + DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); +} + +/* Update the data in CUM to advance over an argument. */ + +void +amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, + bool) +{ + struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v); + /* Update the data in CUM to advance over an argument. */ + + DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump)); + + if (cum->last_arg_reg != -1) + { + int count; + for (count = 0; count < cum->last_arg_len; count++) + cum->regs_already_used |= (1 << (cum->last_arg_reg + count)); + cum->last_arg_reg = -1; + } + + if (cum->formal_type) + cum->formal_type = TREE_CHAIN(cum->formal_type); +} + +/* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. */ + +static struct rtx_def * +_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree); + +static struct rtx_def * +_m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree type) +{ + DPRINTF(("m68k_function_arg numOfRegs=%d\r\n", cum ? cum->num_of_regs : 0)); + + if (cum->num_of_regs) + { + int regbegin = -1, altregbegin = -1, len; + + /* FIXME: The last condition below is a workaround for a bug. */ + if (TARGET_68881 && FLOAT_MODE_P(mode) && + GET_MODE_UNIT_SIZE (mode) <= 12 + && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode)) + { + regbegin = 16; /* FPx */ + len = GET_MODE_NUNITS(mode); + } + /* FIXME: Two last conditions below are workarounds for bugs. */ + else if (INTEGRAL_MODE_P (mode) && mode != CQImode && mode != CHImode) + { + if (!type || POINTER_TYPE_P(type)) + regbegin = 8; /* Ax */ + else + regbegin = 0; /* Dx */ + altregbegin = 8 - regbegin; + len = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; + } + + if (regbegin != -1) + { + int reg; + long mask; + + look_for_reg: mask = 1 << regbegin; + for (reg = 0; reg < cum->num_of_regs; reg++, mask <<= 1) + if (!(cum->regs_already_used & mask)) + { + int end; + for (end = reg; end < cum->num_of_regs && end < reg + len; + end++, mask <<= 1) + if (cum->regs_already_used & mask) + break; + if (end == reg + len) + { + cum->last_arg_reg = reg + regbegin; + cum->last_arg_len = len; + break; + } + } + + if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) + { + DPRINTF(("look for alt reg\n")); + regbegin = altregbegin; + altregbegin = -1; + goto look_for_reg; + } + } + + if (cum->last_arg_reg != -1) + { + DPRINTF(("-> gen_rtx_REG %d\r\n", cum->last_arg_reg)); + return gen_rtx_REG (mode, cum->last_arg_reg); + } + } + return 0; +} + +/* A C expression that controls whether a function argument is passed + in a register, and which register. */ + +struct rtx_def * +amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, + const_tree type, bool) +{ + DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p)); + + struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v); + + tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE; + if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) + { + int i; + cum->last_arg_reg = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low; + cum->last_arg_len = HARD_REGNO_NREGS(cum->last_arg_reg, mode); + + for (i = 0; i < cum->last_arg_len; i++) + { + if (cum->regs_already_used & (1 << (cum->last_arg_reg + i))) + { + error ("two parameters allocated for one register"); + break; + } + cum->regs_already_used |= (1 << (cum->last_arg_reg + i)); + } + return gen_rtx_REG (mode, cum->last_arg_reg); + } + return _m68k_function_arg (cum, mode, type); +} + +void amiga_emit_regparm_clobbers(void) +{ + int x = 0; + for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (mycum.regs_already_used & (1 << i)) + emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i))); + } +} + + +/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, + one if they are compatible, and two if they are nearly compatible + (which causes a warning to be generated). */ + +int +amigaos_comp_type_attributes (const_tree type1, const_tree type2) +{ + DPRINTF(("amigaos_comp_type_attributes\n")); + /* Functions or methods are incompatible if they specify mutually exclusive + ways of passing arguments. */ + if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE) + { + tree arg1, arg2; + arg1 = TYPE_ARG_TYPES(type1); + arg2 = TYPE_ARG_TYPES(type2); + for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2)) + { + tree attr1 = TYPE_ATTRIBUTES(arg1); + tree attr2 = TYPE_ATTRIBUTES(arg2); + if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1)))) + attr1 = NULL_TREE; + if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2)))) + attr2 = NULL_TREE; + if (attr1 && attr2) + { + if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low + != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low) + return 0; + } + else if (attr1 || attr2) + return 0; /* asm attribute only on one side. */ + } + if (arg1 || arg2) + return 0; /* different count of parameters. */ + } + return 1; +} + +/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, + one if they are compatible, and two if they are nearly compatible + (which causes a warning to be generated). */ +#if 0 +static int +m68k_comp_type_attributes (tree type1, tree type2) +{ + + /* Functions or methods are incompatible if they specify mutually + exclusive ways of passing arguments. */ + if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) + { + tree arg1, arg2; + if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != + !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) + || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != + !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) + return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */ + + arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); + arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); + if (arg1 && arg2) + { + int num1 = 0, num2 = 0; + if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) + { + tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); + if (numofregs) + num1 = TREE_INT_CST_LOW (numofregs); + } + if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) + { + tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); + if (numofregs) + num2 = TREE_INT_CST_LOW (numofregs); + } + if (num1 != num2) + return 0; /* Different numbers, or no number in one type. */ + } + } +#ifdef TARGET_AMIGAOS + return amigaos_comp_type_attributes(type1, type2); +#else + return 1; +#endif +} +#endif + +/* end-GG-local */ + + +/* Handle a "regparm", "stkparm" attribute; + arguments as in struct attribute_spec.handler. */ +tree +amigaos_handle_type_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree nnn = *node; + do { // while (0); + DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn))); + if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE + || TREE_CODE (nnn) == METHOD_TYPE) + { + /* 'regparm' accepts one optional argument - number of registers in + single class that should be used to pass arguments. */ + if (is_attribute_p ("regparm", name)) + { + DPRINTF(("regparm found\n")); + + if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn))) + { + error ("`regparm' and `stkparm' are mutually exclusive"); + break; + } + if (args && TREE_CODE (args) == TREE_LIST) + { + tree val = TREE_VALUE(args); + DPRINTF(("regparm with val: %d\n", TREE_CODE(val))); + if (TREE_CODE (val) == INTEGER_CST) + { + int no = TREE_INT_CST_LOW(val); + if (no < 0 || no > AMIGAOS_MAX_REGPARM) + { + error ("`regparm' attribute: value %d not in [0 - %d]", + no, + AMIGAOS_MAX_REGPARM); + break; + } + } + else + { + error ("invalid argument(s) to `regparm' attribute"); + break; + } + } + } + else if (is_attribute_p ("stkparm", name)) + { + if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn))) + { + error ("`regparm' and `stkparm' are mutually exclusive"); + break; + } + } + else if (is_attribute_p ("stackext", name)) + { + if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn))) + { + error ("`stackext' and `interrupt' are mutually exclusive"); + break; + } + } + else if (is_attribute_p ("saveds", name)) + { + } + } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to functions", + IDENTIFIER_POINTER(name)); + } + return NULL_TREE; + } while (0); + // error case + *no_add_attrs = true; + return NULL_TREE; +} + + +extern bool +m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); + +bool +amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, + int *total, bool speed) +{ +// DPRINTF(("outer: %d, opno: %d", outer_code, opno)); + bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); +// *total *= 4; +// fprintf(stderr, "costs: %d, mode=%d, outer=%d, opno=%d, speed=%d, ok=%d\n", *total * 4, mode, outer_code, opno, speed, r); +// debug_rtx(x); + return r; +} + + +/* Output assembly to switch to section NAME with attribute FLAGS. */ + +extern void +amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) +{ + if (0 == strncmp(".text", name, 5)) + name = ".text"; + fprintf (asm_out_file, "\t%s\n", name); +} + +/* Baserel support. */ + +/** + * Does x reference the pic_reg and is const or plus? + */ +int amiga_is_const_pic_ref(const_rtx x) +{ + const_rtx y = x; + if (flag_pic < 3) + return false; + while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS) + y = XEXP(y, 0); + return (x != y && REG_P(y) && REGNO(y) == PIC_REG); +} + + +/* Does operand (which is a symbolic_operand) live in text space? If + so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. + + This function is used in base relative code generation. */ + +int +read_only_operand (rtx operand) +{ + if (GET_CODE (operand) == CONST) + operand = XEXP (XEXP (operand, 0), 0); + if (GET_CODE (operand) == SYMBOL_REF) + return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + return 1; +} + +reg_class_t +amiga_preferred_rename_class2 (reg_class_t rclass ATTRIBUTE_UNUSED, int regno) +{ + if (regno == 0) + return D0_REGS; + if (regno == 8) + return A0_REGS; + return regno_reg_class[regno]; +} diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 52eabeaafb23..3fabe00a678a 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -1004,6 +1004,8 @@ m68k_set_frame_related (rtx_insn *insn) /* Emit RTL for the "prologue" define_expand. */ +extern void amiga_emit_regparm_clobbers(void); + void m68k_expand_prologue (void) { @@ -1012,6 +1014,10 @@ m68k_expand_prologue (void) m68k_compute_frame_layout (); +#ifdef TARGET_AMIGA + amiga_emit_regparm_clobbers(); +#endif + if (flag_stack_usage_info) current_function_static_stack_size = current_frame.size + current_frame.offset; From 9aabe6ab20a761ee0311e7f44fe8d32cc51fc5a2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 19 Apr 2017 14:40:38 +0200 Subject: [PATCH 071/303] @B fix for 64bit builds --- gcc/config/m68k/amigaos.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index ca8eea305345..cf96844ad8cd 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -383,7 +383,7 @@ void amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) { struct amigaos_args * cum = decl == current_function_decl ? &mycum : &othercum; - *cump = (int)cum; + *cump = decl == current_function_decl; cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); @@ -459,7 +459,7 @@ void amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, bool) { - struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v); + struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum; /* Update the data in CUM to advance over an argument. */ DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump)); @@ -487,9 +487,6 @@ amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called. */ -static struct rtx_def * -_m68k_function_arg (CUMULATIVE_ARGS *, machine_mode, const_tree); - static struct rtx_def * _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree type) { @@ -567,7 +564,7 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, { DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p)); - struct amigaos_args *cum = *(struct amigaos_args **) get_cumulative_args (cum_v); + struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum; tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE; if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) @@ -592,12 +589,9 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, void amiga_emit_regparm_clobbers(void) { - int x = 0; for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - { - if (mycum.regs_already_used & (1 << i)) - emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i))); - } + if (mycum.regs_already_used & (1 << i)) + emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i))); } From aad2b7a890503955a2a1aae5ab09f89ed1466769 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 19 Apr 2017 18:37:57 +0200 Subject: [PATCH 072/303] @R mregparm is using old register usage conventions --- gcc/config/m68k/amigaos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index cf96844ad8cd..09934f94c06d 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -537,7 +537,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ } } - if (reg == AMIGAOS_MAX_REGPARM && altregbegin != -1) + if (reg == cum->num_of_regs && altregbegin != -1) { DPRINTF(("look for alt reg\n")); regbegin = altregbegin; From 554f57921f19cad9583eb4f319e12710ab786ceb Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 19 Apr 2017 18:40:05 +0200 Subject: [PATCH 073/303] @B ensure that clobbers for mregparm are not marked as REG_DEAD --- gcc/bbb-opts.c | 43 ++++++++++++++++++++++++++++--------------- gcc/regrename.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 1b1863e9ae8f..2c19242512a2 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -325,20 +325,24 @@ dump_insns (char const * name, bool all) } for (unsigned i = 0; i < insns.size (); ++i) { - insn_info & ii = infos[i]; - fprintf (stderr, "%d: ", i); - for (int j = 0; j < 8; ++j) - if (ii.is_use (j)) - fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j); + if (i < infos.size ()) + { + insn_info & ii = infos[i]; + + for (int j = 0; j < 8; ++j) + if (ii.is_use (j)) + fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j); - for (int j = 8; j < 16; ++j) - if (ii.is_use (j)) - fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8); + for (int j = 8; j < 16; ++j) + if (ii.is_use (j)) + fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8); - if (ii.is_use (FIRST_PSEUDO_REGISTER)) - fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); + if (ii.is_use (FIRST_PSEUDO_REGISTER)) + fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); + + } fprintf (stderr, "\t"); debug_rtx (insns[i]); @@ -502,6 +506,14 @@ update_insn_infos (void) continue; } + if (GET_CODE (pattern) == CLOBBER ) { + /* mark regs as use and def */ + insn_info ud; + ud.scan(pattern); + ud._def |= ud._use; + infos[pos] |= ud; + continue; + } if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER && be_verbose) { fprintf (stderr, "##### "); @@ -882,7 +894,7 @@ opt_strcpy () src = XEXP(src, 1); // if (CONST_INT_P(src) && INTVAL(src) == 0 && find_reg_note (insn, REG_DEAD, dst)) - if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead(REGNO(dst), index)) + if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead (REGNO(dst), index)) { /* now check via NOTICE_UPDATE_CC*/ NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x); @@ -1300,7 +1312,7 @@ merge_add (void) log ("merge_add applied\n"); - rtx_insn * newins1 = make_insn_raw(gen_rtx_SET(dst1, l1)); + rtx_insn * newins1 = make_insn_raw (gen_rtx_SET(dst1, l1)); add_insn_after (newins1, ins1, 0); SET_INSN_DELETED(ins1); @@ -1836,9 +1848,9 @@ namespace class opt_pass * rr = ::global_pass_regrename->clone (); rr->execute (0); - // update_insns (); - // update_insn_infos (); - // bb_reg_rename (); + // update_insns (); + // update_insn_infos (); + // bb_reg_rename (); update_insns (); } @@ -1851,6 +1863,7 @@ namespace { shrink_stack_frame (); update_insns (); + update_insn_infos (); } if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) diff --git a/gcc/regrename.c b/gcc/regrename.c index 696e5557780e..eceb7286e31e 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -892,7 +892,7 @@ regrename_analyze (bitmap bb_mask) if (!range_overlaps_hard_reg_set_p (live, chain->regno, chain->nregs)) continue; - + n_succs_used++; dest_ri = (struct bb_rename_info *)e->dest->aux; @@ -916,7 +916,7 @@ regrename_analyze (bitmap bb_mask) printed = true; fprintf (dump_file, " merging chains %d (->%d) and %d (->%d) [%s]\n", - k, incoming_chain->id, j, chain->id, + k, incoming_chain->id, j, chain->id, reg_names[incoming_chain->regno]); } @@ -1892,6 +1892,28 @@ regrename_finish (void) obstack_free (&rename_obstack, NULL); } +void +mark_early_clobbers_alive (void) +{ + rtx_insn * insn; + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + rtx pattern; + if (NOTE_P(insn) && NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) + break; + + pattern = PATTERN (insn); + if (pattern && GET_CODE(pattern) == CLOBBER) + { + rtx *loc; + + loc = ®_NOTES(insn); + while (*loc) + *loc = XEXP(*loc, 1); + } + } +} + /* Perform register renaming on the current function. */ static unsigned int @@ -1902,6 +1924,8 @@ regrename_optimize (void) df_analyze (); df_set_flags (DF_DEFER_INSN_RESCAN); + mark_early_clobbers_alive (); + regrename_init (false); regrename_analyze (NULL); From 23951fbf9ef78f3106624afd857e738ee56d3663 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 20 Apr 2017 09:34:00 +0200 Subject: [PATCH 074/303] @B modified clobber for regrename with regparm --- gcc/config/m68k/amigaos.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 09934f94c06d..a598406ca132 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -591,7 +591,10 @@ void amiga_emit_regparm_clobbers(void) { for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (mycum.regs_already_used & (1 << i)) - emit_insn(gen_rtx_CLOBBER(Pmode, gen_raw_REG(Pmode, i))); + { + rtx reg = gen_raw_REG(Pmode, i); + emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, reg))); + } } From 6186c919f785d5f0ed760ac3e164510098e106aa Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 20 Apr 2017 18:29:48 +0200 Subject: [PATCH 075/303] @R half way through to own rename --- gcc/bbb-opts.c | 240 +++++++++++++++++++++++++++++++++++++++------- gcc/config/m68k/amigaos.c | 3 +- gcc/regrename.c | 26 +---- 3 files changed, 208 insertions(+), 61 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 2c19242512a2..7a3a716193c4 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -49,6 +49,7 @@ #include "cselib.h" #include "langhooks.h" #include +#include #include static bool be_verbose; @@ -94,11 +95,12 @@ log (char const * fmt, ...) */ struct insn_info { - unsigned _use; - unsigned _def; + unsigned _use; // bit set if registers are used + unsigned _def; // bit set if registers are defined + unsigned _hard; // bit set if registers can't be renamed insn_info () : - _use (0), _def (0) + _use (0), _def (0), _hard (0) { } @@ -107,6 +109,7 @@ struct insn_info { _use = 0; _def = 0; + _hard = 0; } inline void @@ -121,11 +124,18 @@ struct insn_info _def |= 1 << regno; } + inline void + hard (int regno) + { + _hard |= 1 << regno; + } + inline void unset (int regno) { _use &= ~(1 << regno); _def &= ~(1 << regno); + _hard &= ~(1 << regno); } inline bool @@ -140,12 +150,19 @@ struct insn_info return (_def & (1 << regno)) != 0; } + inline bool + is_hard (int regno) + { + return (_hard & (1 << regno)) != 0; + } + inline insn_info operator | (insn_info const & o) const { insn_info t; t._use = _use | o._use; t._def = _def | o._def; + t._hard = _hard | o._hard; return t; } @@ -154,6 +171,7 @@ struct insn_info { _use |= o._use; _def |= o._def; + _hard |= o._hard; return *this; } @@ -162,6 +180,7 @@ struct insn_info { _use &= o._use & o._def; _def &= o._def; + _hard &= o._hard & o._def; return *this; } @@ -177,6 +196,7 @@ struct insn_info insn_info t; t._use = ~_use; t._def = ~_def; + t._hard = ~_hard; return t; } @@ -194,9 +214,12 @@ struct insn_info scan (rtx); unsigned - get_def_mask () const + get_free_mask () const { - if (!_def || _def > 0x7fff) + if (_def & _hard) + return 0; + + if (!_def || _def > 0x1000) return 0; unsigned mask = _def - 1; @@ -204,11 +227,10 @@ struct insn_info if ((mask & ~_def) != mask) return 0; - if (_def > 0x1000) - return 0; if (_def > 0xff) mask &= 0xff00; - return mask; + + return mask & ~_use; } }; @@ -271,6 +293,7 @@ do_reg_rename (rtx x, unsigned oldregno, unsigned newregno) * Collect some data. */ static std::vector insns; +static std::vector proepilogue; static std::vector temp; static std::vector jumps; static std::map insn2index; @@ -283,6 +306,7 @@ static void clear (void) { insns.clear (); + proepilogue.clear (); jumps.clear (); insn2index.clear (); infos.clear (); @@ -333,11 +357,23 @@ dump_insns (char const * name, bool all) for (int j = 0; j < 8; ++j) if (ii.is_use (j)) - fprintf (stderr, ii.is_def (j) ? "*d%d " : "d%d ", j); + { + if (ii.is_hard (j)) + fprintf (stderr, "!"); + if (ii.is_def (j)) + fprintf (stderr, "*"); + fprintf (stderr, "d%d ", j); + } for (int j = 8; j < 16; ++j) if (ii.is_use (j)) - fprintf (stderr, ii.is_def (j) ? "*a%d " : "a%d ", j - 8); + { + if (ii.is_hard (j)) + fprintf (stderr, "!"); + if (ii.is_def (j)) + fprintf (stderr, "*"); + fprintf (stderr, "a%d ", j - 8); + } if (ii.is_use (FIRST_PSEUDO_REGISTER)) fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); @@ -367,6 +403,7 @@ update_insns () df_insn_rescan_all (); + bool inproepilogue = true; /* create a vector with relevant insn. */ for (insn = get_insns (); insn; insn = next) { @@ -379,6 +416,18 @@ update_insns () insn2index.insert (std::make_pair (insn, insns.size ())); insns.push_back (insn); + proepilogue.push_back (inproepilogue); + + if (JUMP_P(insn)) + inproepilogue = false; + } + + if (NOTE_P(insn)) + { + if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) + inproepilogue = false; + else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG) + inproepilogue = true; } } } @@ -447,6 +496,8 @@ update_insn_infos (void) for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) use.use (r); } + /* also mark all registers as not renamable */ + use._hard = use._use; rtx set = single_set (insn); if (set) @@ -457,15 +508,11 @@ update_insn_infos (void) else use.scan (pattern); - /* fix missing defs - a call sets d0 and maybe also d1,a0,a1. */ - if (ii.is_use (0)) - def.def (0); - if (ii.is_use (1)) - def.def (1); - if (ii.is_use (8)) - def.def (8); - if (ii.is_use (9)) - def.def (9); + /* mark scratch registers. */ + def.def (0); + def.def (1); + def.def (8); + def.def (9); infos[pos] = def | use | ii; @@ -501,26 +548,37 @@ update_insn_infos (void) { rtx x = XEXP(pattern, 0); if (REG_P(x)) - ii.use (REGNO(x)); + { + ii.use (REGNO(x)); + ii.hard (REGNO(x)); + } infos[pos] = ii; continue; } - if (GET_CODE (pattern) == CLOBBER ) { + if (GET_CODE (pattern) == CLOBBER) + { /* mark regs as use and def */ insn_info ud; - ud.scan(pattern); + ud.scan (pattern); ud._def |= ud._use; + ud._hard = ud._use; /* don't rename. */ infos[pos] |= ud; continue; - } - if (GET_CODE (pattern) != PARALLEL && GET_CODE (pattern) != CLOBBER && be_verbose) + } + if (GET_CODE (pattern) != PARALLEL && be_verbose) { fprintf (stderr, "##### "); debug_rtx (insn); } - ii.scan (pattern); - infos[pos] = ii; + + insn_info jj; + jj.scan (pattern); + + if (proepilogue[pos]) + jj._hard = jj._use | jj._def; + + infos[pos] = ii | jj; continue; } @@ -549,6 +607,9 @@ update_insn_infos (void) def.def (FIRST_PSEUDO_REGISTER); } + if (proepilogue[pos]) + ii._hard |= use._use | def._def; + infos[pos] = def | use | ii; ii &= ~def; @@ -558,6 +619,114 @@ update_insn_infos (void) } } +static int +bit2regno (unsigned bit) +{ + if (!bit) + return -1; + + unsigned regno = 0; + while (!(bit & 1)) + { + ++regno; + bit >>= 1; + } + return regno; +} + +/* + * Always prefer lower register numbers within the class. + */ +static unsigned +bb_reg_rename (void) +{ +// dump_insns ("rename", 1); + for (unsigned index = 0; index < insns.size (); ++index) + { + insn_info & ii = infos[index]; + const unsigned def = ii._def & ~ii._hard; + unsigned mask = ii.get_free_mask (); + + if (!mask || !def) + continue; + + std::set found; + std::vector todo; + if (index + 1 < insns.size ()) + todo.push_back (index + 1); + + found.insert (index); + /* a register was defined, follow all branches. */ + while (todo.size ()) + { + unsigned pos = todo[todo.size () - 1]; + todo.pop_back (); + + if (found.find (pos) != found.end ()) + continue; + + if (LABEL_P(insns[pos])) + { + if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + continue; + } + + insn_info & jj = infos[pos]; + + /* not used. */ + if (!(jj._use & def)) + continue; + + /* update free regs. */ + mask &= ~jj._use; + mask &= ~jj._def; + if (!mask) + break; + + + found.insert (pos); + + /* follow jump and/or next insn. */ + rtx_insn * insn = insns[pos]; + if (JUMP_P(insn)) + { + std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); + if (j != insn2index.end ()) + todo.push_back (j->second); + + rtx jmppattern = PATTERN (insn); + + rtx jmpsrc = XEXP(jmppattern, 1); + if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + } + else if (pos + 1 < insns.size ()) + todo.push_back (pos + 1); + } + + if (mask) + { + int oldregno = bit2regno (def); + int newregno = bit2regno (mask); + log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], found.size ()); + + for (std::set::iterator i = found.begin (); i != found.end (); ++i) + { +// if (be_verbose) +// debug_rtx (insns[*i]); + do_reg_rename (PATTERN (insns[*i]), oldregno, newregno); + } + + cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); + cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); + return 1; + } + } + return 0; +} + /* * #1 propagate a->b->a moves out of a loop. * @@ -1841,18 +2010,19 @@ namespace done = 0, update_insns (), update_insn_infos (); if (do_elim_dead_assign && elim_dead_assign ()) - done = 0, update_insns (); + done = 0, update_insns (), update_insn_infos (); if (do_bb_reg_rename && ::global_pass_regrename) { - class opt_pass * rr = ::global_pass_regrename->clone (); - rr->execute (0); - - // update_insns (); - // update_insn_infos (); - // bb_reg_rename (); - - update_insns (); +// class opt_pass * rr = ::global_pass_regrename->clone (); +// rr->execute (0); + + while (bb_reg_rename ()) + { + update_insns (); + update_insn_infos (); + done = 0; + } } if (done) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index a598406ca132..dd5707612119 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -589,11 +589,12 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, void amiga_emit_regparm_clobbers(void) { + rtx sp = gen_raw_REG(Pmode, 15); for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (mycum.regs_already_used & (1 << i)) { rtx reg = gen_raw_REG(Pmode, i); - emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, reg))); + emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, gen_rtx_MEM(Pmode, reg)))); } } diff --git a/gcc/regrename.c b/gcc/regrename.c index eceb7286e31e..fad839f8f926 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -1892,28 +1892,6 @@ regrename_finish (void) obstack_free (&rename_obstack, NULL); } -void -mark_early_clobbers_alive (void) -{ - rtx_insn * insn; - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - rtx pattern; - if (NOTE_P(insn) && NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) - break; - - pattern = PATTERN (insn); - if (pattern && GET_CODE(pattern) == CLOBBER) - { - rtx *loc; - - loc = ®_NOTES(insn); - while (*loc) - *loc = XEXP(*loc, 1); - } - } -} - /* Perform register renaming on the current function. */ static unsigned int @@ -1924,8 +1902,6 @@ regrename_optimize (void) df_analyze (); df_set_flags (DF_DEFER_INSN_RESCAN); - mark_early_clobbers_alive (); - regrename_init (false); regrename_analyze (NULL); @@ -1965,7 +1941,7 @@ class pass_regrename : public rtl_opt_pass /* opt_pass methods: */ virtual bool gate (function *) { - return (optimize > 0 && (flag_rename_registers)); + return (optimize > 0 && (flag_rename_registers) && !TARGET_AMIGA); } virtual unsigned int execute (function *) { return regrename_optimize (); } From bab57d7745f2399e3bf6c23f9803ae188bf576ea Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 22 Apr 2017 16:23:35 +0200 Subject: [PATCH 076/303] @R own rename registers seems to work. --- gcc/bbb-opts.c | 350 ++++++++++++++++++++++++++++++++++++-------------------- gcc/cfgbuild.c | 1 + gcc/regrename.c | 3 - 3 files changed, 225 insertions(+), 129 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 7a3a716193c4..1f70ffecc2d4 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -175,13 +175,20 @@ struct insn_info return *this; } - inline insn_info & - operator &= (insn_info const & o) + /* + * update for previous insn. + * - remove regs which are defined here + * - add regs which are used here + * - reset _def + * - restrain _hard to used + */ + inline void + updateWith (insn_info const & o) { - _use &= o._use & o._def; - _def &= o._def; - _hard &= o._hard & o._def; - return *this; + _use &= ~o._def; + _use |= o._use; + _def = 0; + _hard &= ~_use; } inline bool @@ -252,6 +259,24 @@ insn_info::scan (rtx x) } RTX_CODE code = GET_CODE(x); + + /* handle SET and record use and def. */ + if (code == SET) + { + unsigned u = _use; + scan (SET_DEST(x)); + if (REG_P(SET_DEST(x))) + { + _def = _use; + _use = u; + } + scan (SET_SRC(x)); + int code = GET_CODE(SET_SRC(x)); + if (code == ASM_OPERANDS) + _hard |= _def | _use; + return; + } + const char *fmt = GET_RTX_FORMAT(code); for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { @@ -263,14 +288,63 @@ insn_info::scan (rtx x) } } +static rtx +copy_reg(rtx reg, int newregno) +{ + if (newregno < 0) + newregno = REGNO(reg); + rtx x = gen_raw_REG(GET_MODE(reg), newregno); + x->jump = reg->jump; + x->call = reg->call; + x->unchanging = reg->unchanging; + x->volatil = reg->volatil; + x->in_struct = reg->in_struct; + x->used = reg->used; + x->frame_related = reg->frame_related; + x->return_val = reg->return_val; + + x->u.reg.attrs = reg->u.reg.attrs; + return x; +} + +static void +validate_rename (std::vector> & loc, rtx x, unsigned oldregno, unsigned newregno) +{ + RTX_CODE code = GET_CODE(x); + + const char *fmt = GET_RTX_FORMAT(code); + for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + { + rtx y = XEXP(x, i); + if (REG_P(y)) + { + if (REGNO(y) == oldregno) + { + rtx z = copy_reg(y, newregno); + loc.push_back (std::make_pair (&XEXP(x, i), y)); + XEXP(x, i) = z; + } + } + else + validate_rename (loc, y, oldregno, newregno); + } + else if (fmt[i] == 'E') + for (int j = XVECLEN (x, i) - 1; j >= 0; j--) + validate_rename (loc, XVECEXP(x, i, j), oldregno, newregno); + } +} + /* perform reg renaming. */ static void -do_reg_rename (rtx x, unsigned oldregno, unsigned newregno) +do_reg_rename (rtx * loc, unsigned oldregno, unsigned newregno) { + rtx x = *loc; if (REG_P(x)) { if (REGNO(x) == oldregno) - df_ref_change_reg_with_loc (x, newregno); + *loc = copy_reg(x, newregno); return; } @@ -282,10 +356,10 @@ do_reg_rename (rtx x, unsigned oldregno, unsigned newregno) for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - do_reg_rename (XEXP(x, i), oldregno, newregno); + do_reg_rename (&XEXP(x, i), oldregno, newregno); else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - do_reg_rename (XVECEXP(x, i, j), oldregno, newregno); + do_reg_rename (&XVECEXP(x, i, j), oldregno, newregno); } } @@ -356,7 +430,7 @@ dump_insns (char const * name, bool all) insn_info & ii = infos[i]; for (int j = 0; j < 8; ++j) - if (ii.is_use (j)) + if (ii.is_use (j) || ii.is_def (j)) { if (ii.is_hard (j)) fprintf (stderr, "!"); @@ -366,7 +440,7 @@ dump_insns (char const * name, bool all) } for (int j = 8; j < 16; ++j) - if (ii.is_use (j)) + if (ii.is_use (j) || ii.is_def (j)) { if (ii.is_hard (j)) fprintf (stderr, "!"); @@ -436,15 +510,15 @@ static void update_insn_infos (void) { /* prepare insn_info */ - insn_info ii; + insn_info ii0; for (unsigned i = 0; i < insns.size (); ++i) { - infos.push_back (ii); + infos.push_back (ii0); } /* own analyze reg life */ std::vector> todo; - todo.push_back (std::make_pair (insns.size () - 1, ii)); + todo.push_back (std::make_pair (insns.size () - 1, ii0)); int pass = 0; while (!todo.empty ()) @@ -484,7 +558,6 @@ update_insn_infos (void) if (CALL_P(insn)) { - insn_info def; insn_info use; /* add mregparm registers. */ @@ -499,25 +572,16 @@ update_insn_infos (void) /* also mark all registers as not renamable */ use._hard = use._use; - rtx set = single_set (insn); - if (set) - { - use.scan (SET_SRC(set)); - def.scan (SET_DEST(set)); - } - else - use.scan (pattern); + use.scan (pattern); /* mark scratch registers. */ - def.def (0); - def.def (1); - def.def (8); - def.def (9); - - infos[pos] = def | use | ii; + use.def (0); + use.def (1); + use.def (8); + use.def (9); - ii &= ~def; - ii |= use; + infos[pos] = use | ii; + ii.updateWith (use); continue; } @@ -525,95 +589,60 @@ update_insn_infos (void) if (JUMP_P(insn)) { if (ANY_RETURN_P(pattern)) - { - ii.reset (); -// ii.use (0); - } - else - { - ii |= infos[pos]; + ii.reset (); - // check for reg use - ii.scan (PATTERN (insn)); + insn_info use; + use.scan (pattern); + infos[pos] = use | ii; + ii.updateWith (use); - } - infos[pos] = ii; continue; } - rtx set = single_set (insn); - if (set == 0) + if (GET_CODE (pattern) == USE) { - if (GET_CODE (pattern) == USE) - { - rtx x = XEXP(pattern, 0); - if (REG_P(x)) - { - ii.use (REGNO(x)); - ii.hard (REGNO(x)); - } - infos[pos] = ii; - continue; - } - - if (GET_CODE (pattern) == CLOBBER) - { - /* mark regs as use and def */ - insn_info ud; - ud.scan (pattern); - ud._def |= ud._use; - ud._hard = ud._use; /* don't rename. */ - infos[pos] |= ud; - continue; - } - if (GET_CODE (pattern) != PARALLEL && be_verbose) + rtx x = XEXP(pattern, 0); + if (REG_P(x)) { - fprintf (stderr, "##### "); - debug_rtx (insn); + ii.use (REGNO(x)); + ii.hard (REGNO(x)); } + infos[pos] = ii; + continue; + } - insn_info jj; - jj.scan (pattern); - - if (proepilogue[pos]) - jj._hard = jj._use | jj._def; - - infos[pos] = ii | jj; + if (GET_CODE (pattern) == CLOBBER) + { + /* mark regs as use and def */ + insn_info use; + use.scan (pattern); + use._hard = use._use = use._def = use._use | use._def; + infos[pos] = use | ii; + ii.updateWith (use); continue; } - rtx src = SET_SRC(set); - rtx dst = SET_DEST(set); - // scan insn for regs - // a def stop propagation - // a use starts propagation - // also add use to current ii insn_info use; - insn_info def; - - use.scan (src); - if (REG_P(dst)) - def.def (REGNO(dst)); - else if (dst == cc0_rtx) - def.def (FIRST_PSEUDO_REGISTER); - else - use.scan (dst); + use.scan (pattern); + if (single_set (insn) == 0) + use._hard = use._use | use._def; - if (dst != cc0_rtx) + /* if not cc0 defined check for mod. */ + if (!use.is_def (FIRST_PSEUDO_REGISTER)) { CC_STATUS_INIT; NOTICE_UPDATE_CC(PATTERN (insn), insn); if (cc_status.value1 || cc_status.value2) - def.def (FIRST_PSEUDO_REGISTER); + use.def (FIRST_PSEUDO_REGISTER); } + /* mark not renameable in prologue/epilogue. */ if (proepilogue[pos]) - ii._hard |= use._use | def._def; - - infos[pos] = def | use | ii; + use._hard = use._use | use._def; - ii &= ~def; - ii |= use; + ii._use &= ~use._def; + infos[pos] = use | ii; + ii.updateWith (use); } ++pass; } @@ -644,10 +673,15 @@ bb_reg_rename (void) for (unsigned index = 0; index < insns.size (); ++index) { insn_info & ii = infos[index]; - const unsigned def = ii._def & ~ii._hard; - unsigned mask = ii.get_free_mask (); - if (!mask || !def) + /* do not rename if register is hard or used in same statement. */ + const unsigned toRename = ii._def & ~ii._hard & ~ii._use; + if (!toRename) + continue; + + /* get the mask for free registers. */ + unsigned mask = ii.get_free_mask (); + if (!mask) continue; std::set found; @@ -675,16 +709,22 @@ bb_reg_rename (void) insn_info & jj = infos[pos]; /* not used. */ - if (!(jj._use & def)) + if (!(jj._use & toRename)) continue; + /* marked as hard reg -> invalid rename */ + if (jj._hard & toRename) + { + mask = 0; + break; + } + /* update free regs. */ mask &= ~jj._use; mask &= ~jj._def; if (!mask) break; - found.insert (pos); /* follow jump and/or next insn. */ @@ -696,6 +736,11 @@ bb_reg_rename (void) todo.push_back (j->second); rtx jmppattern = PATTERN (insn); + if (GET_CODE(jmppattern) == PARALLEL) + { + return 0; /* can't handle yet. */ +// jmppattern = XVECEXP(jmppattern, 0, 0); + } rtx jmpsrc = XEXP(jmppattern, 1); if (GET_CODE(jmpsrc) == IF_THEN_ELSE) @@ -708,19 +753,69 @@ bb_reg_rename (void) if (mask) { - int oldregno = bit2regno (def); + int oldregno = bit2regno (toRename); int newregno = bit2regno (mask); - log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], found.size ()); - for (std::set::iterator i = found.begin (); i != found.end (); ++i) + /* check the renamed insns. */ + std::vector> locs; + bool ok = true; + std::vector patch; + for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) { -// if (be_verbose) -// debug_rtx (insns[*i]); - do_reg_rename (PATTERN (insns[*i]), oldregno, newregno); + rtx_insn * insn = insns[*i]; + validate_rename (locs, PATTERN (insn), oldregno, newregno); + + if (!locs.empty ()) + { + int num_clobbers_to_add = 0; + int insn_code_number = recog (PATTERN (insn), insn, &num_clobbers_to_add); + if (insn_code_number < 0 || !check_asm_operands (PATTERN (insn))) + { + fprintf (stderr, "renaming %d -> %d failed: ", oldregno, newregno); + debug_rtx (insn); + for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) + { + debug_rtx (*j->first); + debug_rtx (j->second); + } + ok = false; + } + + for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) + *j->first = j->second; + + if (!ok) + { + fprintf (stderr, "restored: ", oldregno, newregno); + debug_rtx (insn); + for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) + { + debug_rtx (*j->first); + debug_rtx (j->second); + } + } + locs.clear (); + + patch.push_back(*i); + } } - cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); - cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); + if (!ok) + continue; + + log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); + + for (std::vector::iterator i = patch.begin (); i != patch.end (); ++i) + { + rtx_insn * insn = insns[*i]; + rtx pattern = PATTERN (insn); + SET_INSN_DELETED(insn); + do_reg_rename (&pattern, oldregno, newregno); + emit_insn_after(pattern, insn); + } + +// cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); +// cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); return 1; } } @@ -1209,7 +1304,7 @@ commute_add_move (void) SET_INSN_DELETED(insn); - insn = emit_insn_before (newinsn, next); + insn = emit_insn_before (PATTERN (newinsn), next); add_reg_note (next, REG_INC, reg1dst); @@ -1295,28 +1390,33 @@ const_cmp_to_sub (void) continue; int intval = -INTVAL(srcp); - if (intval < -8 || intval > 7) + if (intval < -8 || intval > 7 || intval == 0) continue; enum machine_mode mode = GET_MODE(dstp); + if (GET_MODE_SIZE(mode) > 4) + continue; + + // printf("mode size: %d\n", GET_MODE_SIZE(mode)); + rtx reg = dstp == left ? right : left; - rtx plus = gen_rtx_PLUS(mode, reg, gen_rtx_CONST_INT (mode, intval)); + rtx plus = gen_rtx_PLUS(mode, copy_reg(reg, -1), gen_rtx_CONST_INT (mode, intval)); - rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(reg, plus)); + rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg(reg, -1), plus)); int num_clobbers_to_add = 0; int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add); - if (insn_code_number >= 0 && !check_asm_operands (PATTERN (neuprev))) + if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev))) continue; // also convert current statement to cmp #0, reg SET_INSN_DELETED(insn); - rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, reg, gen_rtx_CONST_INT(mode, 0))); + rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copy_reg(reg, -1), gen_rtx_CONST_INT(mode, 0))); insn = emit_insn_after (neu, prev); add_reg_note (insn, REG_DEAD, reg); SET_INSN_DELETED(prev); - prev = emit_insn_before (neuprev, insn); + prev = emit_insn_before (PATTERN (neuprev), insn); log ("const_cmp_to_sub replaced reg-reg compare with sub\n"); @@ -1537,7 +1637,7 @@ shrink_stack_frame (void) return 0; bool usea5 = false; - unsigned paramstart = 4; + int paramstart = 4; int a5offset = 0; /* @@ -1696,6 +1796,9 @@ shrink_stack_frame (void) insn_info ii; for (unsigned i = 0; i < infos.size (); ++i) { + if (proepilogue[i]) + continue; + insn_info & jj = infos[i]; ii |= jj; } @@ -1914,8 +2017,6 @@ shrink_stack_frame (void) return 0; } -extern class opt_pass * global_pass_regrename; - namespace { @@ -2012,11 +2113,8 @@ namespace if (do_elim_dead_assign && elim_dead_assign ()) done = 0, update_insns (), update_insn_infos (); - if (do_bb_reg_rename && ::global_pass_regrename) + if (do_bb_reg_rename) { -// class opt_pass * rr = ::global_pass_regrename->clone (); -// rr->execute (0); - while (bb_reg_rename ()) { update_insns (); diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index c1ec46ad8d7f..1f488dc54544 100644 --- gcc/cfgbuild.c +++ gcc/cfgbuild.c @@ -55,6 +55,7 @@ inside_basic_block_p (const rtx_insn *insn) case DEBUG_INSN: return true; + case DEBUG_IMPLICIT_PTR: case JUMP_TABLE_DATA: case BARRIER: case NOTE: diff --git a/gcc/regrename.c b/gcc/regrename.c index fad839f8f926..3d1e87af39fc 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -1913,8 +1913,6 @@ regrename_optimize (void) return 0; } -class opt_pass * global_pass_regrename; - namespace { const pass_data pass_data_regrename = @@ -1935,7 +1933,6 @@ class pass_regrename : public rtl_opt_pass pass_regrename (gcc::context *ctxt) : rtl_opt_pass (pass_data_regrename, ctxt) { - ::global_pass_regrename = this; } /* opt_pass methods: */ From 7b2b67ccbe0e6ea8a226071a001cdeac5a493a1d Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 22 Apr 2017 16:31:08 +0200 Subject: [PATCH 077/303] @R restored original regrename.c, since no longer used with TARGET_AMIGA. Only left the fix for df --- gcc/regrename.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/gcc/regrename.c b/gcc/regrename.c index 3d1e87af39fc..1ed6557ee713 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -356,9 +356,8 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, { bool has_preferred_class; enum reg_class preferred_class; + int pass; int best_new_reg = old_reg; - int new_reg; - int hit = 0; /* Further narrow the set of registers we can use for renaming. If the chain needs a call-saved register, mark the call-used @@ -371,14 +370,14 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, /* Compute preferred rename class of super union of all the classes in the chain. */ - preferred_class = (enum reg_class) targetm.preferred_rename_class2 ( - super_class, old_reg); + preferred_class + = (enum reg_class) targetm.preferred_rename_class (super_class); /* Pick and check the register from the tied chain iff the tied chain is not renamed. */ if (this_head->tied_chain && !this_head->tied_chain->renamed - && check_new_reg_p (old_reg, this_head->tied_chain->regno, this_head, - *unavailable)) + && check_new_reg_p (old_reg, this_head->tied_chain->regno, + this_head, *unavailable)) return this_head->tied_chain->regno; /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass @@ -388,10 +387,14 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, If PREFERRED_CLASS is NO_REGS, we iterate over all registers in ascending order without any preference. */ has_preferred_class = (preferred_class != NO_REGS); + for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++) + { + int new_reg; for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++) { if (has_preferred_class - && !TEST_HARD_REG_BIT(reg_class_contents[preferred_class], + && (pass == 0) + != TEST_HARD_REG_BIT (reg_class_contents[preferred_class], new_reg)) continue; @@ -405,11 +408,14 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, don't belong to PREFERRED_CLASS to registers that do, even though the latters were used not very long ago. Also use a register if no best_new_reg was found till now */ - if (new_reg < old_reg || !hit) - { - hit = 1; + if (((pass == 0 || !has_preferred_class) + && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], + best_new_reg)) + || tick[best_new_reg] > tick[new_reg]) best_new_reg = new_reg; } + if (pass == 0 && best_new_reg != old_reg) + break; } return best_new_reg; } @@ -1932,8 +1938,7 @@ class pass_regrename : public rtl_opt_pass public: pass_regrename (gcc::context *ctxt) : rtl_opt_pass (pass_data_regrename, ctxt) - { - } + {} /* opt_pass methods: */ virtual bool gate (function *) @@ -1943,11 +1948,6 @@ class pass_regrename : public rtl_opt_pass virtual unsigned int execute (function *) { return regrename_optimize (); } - opt_pass * clone () - { - return new pass_regrename(m_ctxt); - } - }; // class pass_regrename } // anon namespace From 8425bbc011d5d94d7e2270c00b904da4170fc644 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 22 Apr 2017 19:54:50 +0200 Subject: [PATCH 078/303] @B fix hard reg tracking in parallel insns, @I some cleanup --- gcc/bbb-opts.c | 144 ++++++++++++++++++++++++--------------------------------- 1 file changed, 61 insertions(+), 83 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 1f70ffecc2d4..e7de83e59c07 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -26,9 +26,30 @@ * #1 propagate_moves * check if a->b->a can be moved out of a loop. * - * #2 strcpy_opt + * #2 strcpy * check if a temp reg can be eliminated. * + * #3 const_comp_sub + * convert a compare with int constant into sub statement. + * + * #4 merge_add + * merge adds + * + * #5 elim_dead_assign + * eliminate some dead assignments. + * + * #6 shrink stack frame + * remove push/pop for unused variables + * + * #7 rename register + * rename registers without breaking register parameters, inline asm etc. + * + * Lessons learned: + * + * - do not trust existing code, better delete insns and inster a new one. + * - do not modify insns, create new insns from pattern + * - do not reuse registers, create new reg rtx instances + * */ #include "config.h" @@ -55,10 +76,12 @@ static bool be_verbose; extern struct lang_hooks lang_hooks; + +/* Lookup of the current function name. */ extern tree current_function_decl; static tree last_function_decl; static char const * -getCurrentFunctionName () +get_current_function_name () { static char fxname[512]; if (current_function_decl == NULL) @@ -68,6 +91,7 @@ getCurrentFunctionName () return fxname; } +/* a simple log to stdout. */ static int log (char const * fmt, ...) { @@ -79,7 +103,7 @@ log (char const * fmt, ...) if (last_function_decl != current_function_decl) { last_function_decl = current_function_decl; - printf (":bbb: in '%s'\n", getCurrentFunctionName ()); + printf (":bbb: in '%s'\n", get_current_function_name ()); } printf (":bbb: "); int retval = vprintf (fmt, args); @@ -88,7 +112,7 @@ log (char const * fmt, ...) return retval; } -/* Enough for m68k. +/* Information for each insn to detect alive registers. Enough for m68k. * Why a class? Maybe extend it for general usage. * * Track use & def separate to determine starting points. @@ -220,6 +244,7 @@ struct insn_info void scan (rtx); + /* return bits for alternate free registers. */ unsigned get_free_mask () const { @@ -267,7 +292,7 @@ insn_info::scan (rtx x) scan (SET_DEST(x)); if (REG_P(SET_DEST(x))) { - _def = _use; + _def |= _use; _use = u; } scan (SET_SRC(x)); @@ -288,12 +313,13 @@ insn_info::scan (rtx x) } } +/* create a copy for a reg. Optional specify a new register number. */ static rtx -copy_reg(rtx reg, int newregno) +copy_reg (rtx reg, int newregno) { if (newregno < 0) newregno = REGNO(reg); - rtx x = gen_raw_REG(GET_MODE(reg), newregno); + rtx x = gen_raw_REG (GET_MODE(reg), newregno); x->jump = reg->jump; x->call = reg->call; x->unchanging = reg->unchanging; @@ -307,8 +333,9 @@ copy_reg(rtx reg, int newregno) return x; } +/* Rename the register plus track all locs to undo these changes. */ static void -validate_rename (std::vector> & loc, rtx x, unsigned oldregno, unsigned newregno) +temp_reg_rename (std::vector> & loc, rtx x, unsigned oldregno, unsigned newregno) { RTX_CODE code = GET_CODE(x); @@ -322,44 +349,17 @@ validate_rename (std::vector> & loc, rtx x, unsigned oldre { if (REGNO(y) == oldregno) { - rtx z = copy_reg(y, newregno); + rtx z = copy_reg (y, newregno); loc.push_back (std::make_pair (&XEXP(x, i), y)); XEXP(x, i) = z; } } else - validate_rename (loc, y, oldregno, newregno); + temp_reg_rename (loc, y, oldregno, newregno); } else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - validate_rename (loc, XVECEXP(x, i, j), oldregno, newregno); - } -} - -/* perform reg renaming. */ -static void -do_reg_rename (rtx * loc, unsigned oldregno, unsigned newregno) -{ - rtx x = *loc; - if (REG_P(x)) - { - if (REGNO(x) == oldregno) - *loc = copy_reg(x, newregno); - return; - } - - if (x == cc0_rtx) - return; - - RTX_CODE code = GET_CODE(x); - const char *fmt = GET_RTX_FORMAT(code); - for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - do_reg_rename (&XEXP(x, i), oldregno, newregno); - else if (fmt[i] == 'E') - for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - do_reg_rename (&XVECEXP(x, i, j), oldregno, newregno); + temp_reg_rename (loc, XVECEXP(x, i, j), oldregno, newregno); } } @@ -758,64 +758,42 @@ bb_reg_rename (void) /* check the renamed insns. */ std::vector> locs; + std::vector> patch; bool ok = true; - std::vector patch; + for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) { rtx_insn * insn = insns[*i]; - validate_rename (locs, PATTERN (insn), oldregno, newregno); + /* temp rename. */ + temp_reg_rename (locs, PATTERN (insn), oldregno, newregno); if (!locs.empty ()) { int num_clobbers_to_add = 0; int insn_code_number = recog (PATTERN (insn), insn, &num_clobbers_to_add); if (insn_code_number < 0 || !check_asm_operands (PATTERN (insn))) - { - fprintf (stderr, "renaming %d -> %d failed: ", oldregno, newregno); - debug_rtx (insn); - for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) - { - debug_rtx (*j->first); - debug_rtx (j->second); - } - ok = false; - } + ok = false; + /* undo temp change but keep loc and new register. */ for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) - *j->first = j->second; - - if (!ok) { - fprintf (stderr, "restored: ", oldregno, newregno); - debug_rtx (insn); - for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) - { - debug_rtx (*j->first); - debug_rtx (j->second); - } + patch.push_back (std::make_pair (j->first, *j->first)); + *j->first = j->second; } - locs.clear (); - patch.push_back(*i); + locs.clear (); } } if (!ok) continue; - log ("bb_reg_rename %s -> %s (%d insns)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); + log ("bb_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); - for (std::vector::iterator i = patch.begin (); i != patch.end (); ++i) - { - rtx_insn * insn = insns[*i]; - rtx pattern = PATTERN (insn); - SET_INSN_DELETED(insn); - do_reg_rename (&pattern, oldregno, newregno); - emit_insn_after(pattern, insn); - } + /* apply all changes. */ + for (std::vector>::iterator j = patch.begin (); j != patch.end (); ++j) + *j->first = j->second; -// cselib_invalidate_rtx (gen_raw_REG (SImode, oldregno)); -// cselib_invalidate_rtx (gen_raw_REG (SImode, newregno)); return 1; } } @@ -879,7 +857,7 @@ bb_reg_rename (void) * The label must only be reachable by the exit jump. */ static unsigned -propagate_moves () +opt_propagate_moves () { unsigned change_count = 0; rtx_insn * current_label = 0; @@ -1341,7 +1319,7 @@ commute_add_move (void) * */ static unsigned -const_cmp_to_sub (void) +opt_const_cmp_to_sub (void) { unsigned change_count = 0; #if HAVE_cc0 @@ -1400,9 +1378,9 @@ const_cmp_to_sub (void) // printf("mode size: %d\n", GET_MODE_SIZE(mode)); rtx reg = dstp == left ? right : left; - rtx plus = gen_rtx_PLUS(mode, copy_reg(reg, -1), gen_rtx_CONST_INT (mode, intval)); + rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval)); - rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg(reg, -1), plus)); + rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus)); int num_clobbers_to_add = 0; int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add); @@ -1532,7 +1510,7 @@ elim_dead_assign (void) add.l d1,a1 */ static unsigned -merge_add (void) +opt_merge_add (void) { unsigned change_count = 0; for (unsigned index = 0; index + 2 < insns.size (); ++index) @@ -1623,7 +1601,7 @@ clear_temp () * newstartvalue = startvalue - omitted pushes */ static unsigned -shrink_stack_frame (void) +opt_shrink_stack_frame (void) { /* nothing to do. */ if (!insns.size ()) @@ -2100,14 +2078,14 @@ namespace if (do_commute_add_move && commute_add_move ()) done = 0, update_insns (); - if (do_propagate_moves && propagate_moves ()) + if (do_propagate_moves && opt_propagate_moves ()) done = 0, update_insns (); update_insn_infos (); - if (do_const_cmp_to_sub && const_cmp_to_sub ()) + if (do_const_cmp_to_sub && opt_const_cmp_to_sub ()) done = 0, update_insns (), update_insn_infos (); - if (do_merge_add && merge_add ()) + if (do_merge_add && opt_merge_add ()) done = 0, update_insns (), update_insn_infos (); if (do_elim_dead_assign && elim_dead_assign ()) @@ -2129,7 +2107,7 @@ namespace if (do_shrink_stack_frame) { - shrink_stack_frame (); + opt_shrink_stack_frame (); update_insns (); update_insn_infos (); } From cfd147a3142a4e1b6495f4f1c57d2b236c991c95 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 00:05:15 +0200 Subject: [PATCH 079/303] @N shrink-stack-frame is now also dropping unused frame pointers. @I more cleanup --- gcc/bbb-opts.c | 115 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 45 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index e7de83e59c07..d684e280a17e 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -367,7 +367,7 @@ temp_reg_rename (std::vector> & loc, rtx x, unsigned oldre * Collect some data. */ static std::vector insns; -static std::vector proepilogue; +static std::vector proepilogue; static std::vector temp; static std::vector jumps; static std::map insn2index; @@ -477,7 +477,7 @@ update_insns () df_insn_rescan_all (); - bool inproepilogue = true; + char inproepilogue = 1; /* create a vector with relevant insn. */ for (insn = get_insns (); insn; insn = next) { @@ -493,32 +493,34 @@ update_insns () proepilogue.push_back (inproepilogue); if (JUMP_P(insn)) - inproepilogue = false; + inproepilogue = 0; } if (NOTE_P(insn)) { if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) - inproepilogue = false; + inproepilogue = 0; else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG) - inproepilogue = true; + inproepilogue = 2; } } } +/* This is the important function to track register usage plus hard/live state. + * + * Start at bottom and work upwards. On all labels trigger all jumps referring to this label. + * A set destination into a register is a def. All other register references are an use. + * Hard registers cann't be renamed and are mandatory for regparms and asm_operands. + */ static void update_insn_infos (void) { /* prepare insn_info */ - insn_info ii0; - for (unsigned i = 0; i < insns.size (); ++i) - { - infos.push_back (ii0); - } + infos.resize (insns.size ()); /* own analyze reg life */ std::vector> todo; - todo.push_back (std::make_pair (insns.size () - 1, ii0)); + todo.push_back (std::make_pair (insns.size () - 1, insn_info ())); int pass = 0; while (!todo.empty ()) @@ -531,9 +533,11 @@ update_insn_infos (void) for (int pos = p.first; pos >= 0; --pos) { rtx_insn * insn = insns[pos]; - if (!insn) // moved to temp for stack frame cleanup + /* can be NULL as used in opt_shrink_stack_frame(). */ + if (!insn) continue; + /* no new information -> break. */ if (pass && infos[pos].contains (ii)) break; @@ -648,6 +652,7 @@ update_insn_infos (void) } } +/* convert the lowest set bit into a register number. */ static int bit2regno (unsigned bit) { @@ -667,7 +672,7 @@ bit2regno (unsigned bit) * Always prefer lower register numbers within the class. */ static unsigned -bb_reg_rename (void) +opt_reg_rename (void) { // dump_insns ("rename", 1); for (unsigned index = 0; index < insns.size (); ++index) @@ -738,8 +743,7 @@ bb_reg_rename (void) rtx jmppattern = PATTERN (insn); if (GET_CODE(jmppattern) == PARALLEL) { - return 0; /* can't handle yet. */ -// jmppattern = XVECEXP(jmppattern, 0, 0); + return 0; /* can't handle yet. Abort renaming. */ } rtx jmpsrc = XEXP(jmppattern, 1); @@ -788,7 +792,7 @@ bb_reg_rename (void) if (!ok) continue; - log ("bb_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); + log ("opt_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); /* apply all changes. */ for (std::vector>::iterator j = patch.begin (); j != patch.end (); ++j) @@ -1470,6 +1474,10 @@ opt_const_cmp_to_sub (void) return change_count; } +/* + * Some optimizations (e.g. propagate_moves) might result into an unuses assignment behind the loop. + * delete those insns. + */ static unsigned elim_dead_assign (void) { @@ -1570,6 +1578,9 @@ opt_merge_add (void) return change_count; } +/* + * Move the insns back from temp to insns. + */ static void clear_temp () { @@ -1607,6 +1618,7 @@ opt_shrink_stack_frame (void) if (!insns.size ()) return 0; + std::vector a5pos; temp.resize (insns.size ()); unsigned pos = 0; @@ -1622,16 +1634,11 @@ opt_shrink_stack_frame (void) * Move prologue to temp. * Only register push and parallel insn unless its a link a5 are moved. */ - rtx_insn * prev = get_insns (); for (; pos < insns.size ();) { insn = insns[pos]; - /* check for prologue end. */ - for (; prev != insn; prev = NEXT_INSN (prev)) - if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_PROLOGUE_END) - break; - if (prev != insn) + if (proepilogue[pos] != 1) break; rtx pattern = PATTERN (insn); @@ -1642,6 +1649,7 @@ opt_shrink_stack_frame (void) /* ignore link a5 */ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) { + a5pos.push_back (pos); usea5 = true; set = XVECEXP(pattern, 0, 2); a5offset = INTVAL(XEXP(SET_SRC(set), 1)); @@ -1657,6 +1665,9 @@ opt_shrink_stack_frame (void) } if (GET_CODE(pattern) != SET) { + /* (set (mem:BLK (scratch) [0 A8]) (unspec:BLK [ ...)) */ + if (MEM_P(SET_DEST(pattern)) && GET_CODE(SET_SRC(pattern)) == UNSPEC) + a5pos.push_back (pos); ++pos; continue; } @@ -1701,21 +1712,13 @@ opt_shrink_stack_frame (void) unsigned prologueend = pos; - prev = insn; - /* search epilogues - there can be multiple epilogues. */ while (pos < insns.size ()) { while (pos < insns.size ()) { - insn = insns[pos]; - for (; prev != insn; prev = NEXT_INSN (prev)) - if (NOTE_P(prev) && NOTE_KIND(prev) == NOTE_INSN_EPILOGUE_BEG) - break; - - if (prev != insn) + if (proepilogue[pos]) break; - ++pos; } @@ -1723,13 +1726,10 @@ opt_shrink_stack_frame (void) for (; pos < insns.size (); ++pos) { insn = insns[pos]; - if (JUMP_P(insn)) /* return */ - break; - - if (LABEL_P(insn)) + if (JUMP_P(insn) || LABEL_P(insn) || !proepilogue[pos]) break; - /* omitt the frame pointer a5. */ + /* omit the frame pointer a5. */ rtx pattern = PATTERN (insn); if (GET_CODE(pattern) == PARALLEL) { @@ -1737,7 +1737,10 @@ opt_shrink_stack_frame (void) rtx dst = SET_DEST(set); /* unlink is last. */ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) - break; + { + a5pos.push_back (pos); + break; + } /* movem. */ temp[pos] = insn; @@ -1766,7 +1769,6 @@ opt_shrink_stack_frame (void) } } } - prev = insn; ++pos; } /* gather usage stats without prologue/epilogue */ @@ -1989,6 +1991,33 @@ opt_shrink_stack_frame (void) } } + if (usea5 && a5offset == -4) + { + for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) + { + temp[*i] = insns[*i]; + insns[*i] = 0; + } + update_insn_infos (); + insn_info ii; + for (unsigned i = 0; i < infos.size (); ++i) + { + if (proepilogue[i]) + continue; + + insn_info & jj = infos[i]; + ii |= jj; + } + unsigned freemask = ~ii._use; + + if (freemask & (1 << FRAME_POINTER_REGNUM)) + { + log ("dropping unused frame pointer\n"); + for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) + SET_INSN_DELETED(temp[*i]); + } + } + /* restore stack insns */ clear_temp (); @@ -2000,14 +2029,14 @@ namespace const pass_data pass_data_bbb_optimizations = { RTL_PASS, /* type */ - "bbb", /* name */ + "bebbo's-optimizers", /* name */ OPTGROUP_NONE, /* optinfo_flags */ TV_NONE, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - ( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */ + 0, /* todo_flags_finish */ }; class pass_bbb_optimizations : public rtl_opt_pass @@ -2053,10 +2082,6 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { - df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN); - df_note_add_problem (); - df_analyze (); - be_verbose = strchr (string_bbb_opts, 'v'); bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); @@ -2093,7 +2118,7 @@ namespace if (do_bb_reg_rename) { - while (bb_reg_rename ()) + while (opt_reg_rename ()) { update_insns (); update_insn_infos (); From 0461e994f5f13ef6becd36265f33fa8812f25cb3 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 00:12:10 +0200 Subject: [PATCH 080/303] @V bump version --- gcc/BASE-VER | 2 +- gcc/DATESTAMP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/BASE-VER b/gcc/BASE-VER index 6352d5267189..91eb9361dcd3 100644 --- gcc/BASE-VER +++ gcc/BASE-VER @@ -1 +1 @@ -6.3.1b +6.3.1c diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e30948e24831..e9793b647365 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170320 +20170423 From 7cf932893a3328d06b1c1eb4c51b9eaf39db8bc1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 10:57:09 +0200 Subject: [PATCH 081/303] @B some fixes in opt_reg_rename --- gcc/bbb-opts.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index d684e280a17e..a8122e80998e 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -238,6 +238,8 @@ struct insn_info return false; if (o._use & ~_use) return false; + if (o._hard & ~_hard) + return false; return true; } @@ -298,7 +300,7 @@ insn_info::scan (rtx x) scan (SET_SRC(x)); int code = GET_CODE(SET_SRC(x)); if (code == ASM_OPERANDS) - _hard |= _def | _use; + _use = _hard |= _def | _use; return; } @@ -713,16 +715,13 @@ opt_reg_rename (void) insn_info & jj = infos[pos]; - /* not used. */ - if (!(jj._use & toRename)) - continue; - /* marked as hard reg -> invalid rename */ if (jj._hard & toRename) - { - mask = 0; - break; - } + mask = 0; + + /* defined again -> invalid rename */ + if (jj._def & toRename) + mask = 0; /* update free regs. */ mask &= ~jj._use; @@ -730,6 +729,10 @@ opt_reg_rename (void) if (!mask) break; + /* not used. */ + if (!(jj._use & toRename)) + continue; + found.insert (pos); /* follow jump and/or next insn. */ @@ -1902,7 +1905,7 @@ opt_shrink_stack_frame (void) else { /* pop */ - if (usea5) + if (usea5 && a5offset != -4) { x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); From fbc0890125f5455fbd9947d439f0caab8b0a4e12 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 10:59:12 +0200 Subject: [PATCH 082/303] @R change template >> to > > for crappy compilers --- gcc/bbb-opts.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a8122e80998e..90751c4165d3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -337,7 +337,7 @@ copy_reg (rtx reg, int newregno) /* Rename the register plus track all locs to undo these changes. */ static void -temp_reg_rename (std::vector> & loc, rtx x, unsigned oldregno, unsigned newregno) +temp_reg_rename (std::vector > & loc, rtx x, unsigned oldregno, unsigned newregno) { RTX_CODE code = GET_CODE(x); @@ -521,7 +521,7 @@ update_insn_infos (void) infos.resize (insns.size ()); /* own analyze reg life */ - std::vector> todo; + std::vector > todo; todo.push_back (std::make_pair (insns.size () - 1, insn_info ())); int pass = 0; @@ -764,8 +764,8 @@ opt_reg_rename (void) int newregno = bit2regno (mask); /* check the renamed insns. */ - std::vector> locs; - std::vector> patch; + std::vector > locs; + std::vector > patch; bool ok = true; for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) @@ -782,7 +782,7 @@ opt_reg_rename (void) ok = false; /* undo temp change but keep loc and new register. */ - for (std::vector>::iterator j = locs.begin (); j != locs.end (); ++j) + for (std::vector >::iterator j = locs.begin (); j != locs.end (); ++j) { patch.push_back (std::make_pair (j->first, *j->first)); *j->first = j->second; @@ -798,7 +798,7 @@ opt_reg_rename (void) log ("opt_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); /* apply all changes. */ - for (std::vector>::iterator j = patch.begin (); j != patch.end (); ++j) + for (std::vector >::iterator j = patch.begin (); j != patch.end (); ++j) *j->first = j->second; return 1; From d98fb77f2e7d620cb8c901f806e8d938b3e7f07f Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 13:38:06 +0200 Subject: [PATCH 083/303] @B init insn_infos before running opt_strcpy --- gcc/bbb-opts.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 90751c4165d3..2858daa6c908 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -390,24 +390,23 @@ clear (void) /* * return true if the register is DEAD. + * Do not check at jumps. */ static bool -is_reg_dead (unsigned regno, unsigned pos) +is_reg_dead (unsigned regno, unsigned _pos) { - for (;;) + // skip labels. + for (unsigned pos = _pos + 1; pos < infos.size (); ++pos) { - if (pos + 1 >= infos.size ()) - return true; + insn_info & ii0 = infos[pos]; + // skip entries without info + if (!ii0._def && !ii0._use && !ii0._hard) + continue; - rtx_insn * insn = insns[pos + 1]; - if (!LABEL_P(insn) && GET_CODE(insn) != USE) - break; - ++pos; + // not dead if usage is reported in the next statement + return !ii0.is_use (regno) && !ii0.is_hard (regno); } - - insn_info & ii0 = infos[pos + 1]; - // not dead if usage is reported in the next statement - return !ii0.is_use (regno); + return true; } /* @@ -720,12 +719,9 @@ opt_reg_rename (void) mask = 0; /* defined again -> invalid rename */ - if (jj._def & toRename) + if ((jj._def & toRename) && !(jj._use & toRename)) mask = 0; - /* update free regs. */ - mask &= ~jj._use; - mask &= ~jj._def; if (!mask) break; @@ -733,6 +729,12 @@ opt_reg_rename (void) if (!(jj._use & toRename)) continue; + /* update free regs. */ + mask &= ~jj._use; + mask &= ~jj._def; + if (!mask) + break; + found.insert (pos); /* follow jump and/or next insn. */ @@ -2100,6 +2102,7 @@ namespace { int done = 1; update_insns (); + update_insn_infos (); if (do_opt_strcpy && opt_strcpy ()) done = 0, update_insns (); From 78db2bc90ad5701e59107a782343b1d25937102e Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 23:08:07 +0200 Subject: [PATCH 084/303] @B fix regparm with return values > 64bit --- gcc/config/m68k/amigaos.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index dd5707612119..d385ab1ff108 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -435,6 +435,15 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) if (!next_param && TREE_VALUE (param) != void_type_node) cum->num_of_regs = 0; } + + /* check for return values passed in a0 */ + if (cum->num_of_regs) + { + tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); + int sz = type ? TREE_INT_CST_LOW(type) : 0; + if (sz > 64) /* mark a0 as already used. */ + cum->regs_already_used |= 1<<8; + } } //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM) From 5c0207b6ae6544541c786c74d57ddfcbe48b7a48 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 23:08:48 +0200 Subject: [PATCH 085/303] @B fix __regards definition --- gcc/config/m68k/m68kamigaos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 68f3277bd87c..20e0b66face2 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -194,7 +194,7 @@ amiga_declare_object = 0 builtin_define ("__saveds=__attribute__((__saveds__))"); \ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \ builtin_define ("__stackext=__attribute__((__stackext__))"); \ - builtin_define ("__regargs=__attribute__((__regparm__))"); \ + builtin_define ("__regargs=__attribute__((__regparm__(2)))"); \ builtin_define ("__stdargs=__attribute__((__stkparm__))"); \ builtin_define ("__aligned=__attribute__((__aligned__(4)))"); \ builtin_define_std ("amiga"); \ From 827a96ae044a2b7925972b04ec8e24c0999daa71 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 23 Apr 2017 23:09:27 +0200 Subject: [PATCH 086/303] @B fix return val sizes and so... --- gcc/bbb-opts.c | 55 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 2858daa6c908..d0288f254f9c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -476,7 +476,7 @@ update_insns () rtx_insn *insn, *next; clear (); - df_insn_rescan_all (); + // df_insn_rescan_all (); char inproepilogue = 1; /* create a vector with relevant insn. */ @@ -593,10 +593,25 @@ update_insn_infos (void) if (JUMP_P(insn)) { + insn_info use; if (ANY_RETURN_P(pattern)) - ii.reset (); + { + tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); + int sz = type ? TREE_INT_CST_LOW(type) : 0; + // log ("return size %d\n", sz); + if (sz <= 64) + { + use.hard (0); + use.use (0); + if (sz > 32) + { + use.hard (1); + use.use (1); + } + } + ii.reset (); + } - insn_info use; use.scan (pattern); infos[pos] = use | ii; ii.updateWith (use); @@ -752,7 +767,7 @@ opt_reg_rename (void) } rtx jmpsrc = XEXP(jmppattern, 1); - if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + if (jmpsrc && GET_CODE(jmpsrc) == IF_THEN_ELSE) if (pos + 1 < insns.size ()) todo.push_back (pos + 1); } @@ -1065,8 +1080,8 @@ opt_propagate_moves () j = reg_reg.end (); inc = false; - df_insn_rescan (newii); - df_insn_rescan (newjj); + // df_insn_rescan (newii); + // df_insn_rescan (newjj); /* add fixes if there were jumps out of the loop. */ if (jump_out.size ()) @@ -1078,7 +1093,7 @@ opt_propagate_moves () rtx neu = gen_rtx_SET( dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k]))); rtx_insn * neui = emit_insn_after (neu, jump_out[k]); - df_insn_rescan (neui); + // df_insn_rescan (neui); } } ++change_count; @@ -1178,7 +1193,7 @@ opt_strcpy () SET_INSN_DELETED(x2reg); SET_INSN_DELETED(insn); - df_insn_rescan (reg2x); + // df_insn_rescan (reg2x); ++change_count; } @@ -1238,7 +1253,7 @@ opt_strcpy () (nil))) */ static unsigned -commute_add_move (void) +opt_commute_add_move (void) { unsigned change_count = 0; @@ -1295,8 +1310,8 @@ commute_add_move (void) add_reg_note (next, REG_INC, reg1dst); - df_insn_rescan (insn); - df_insn_rescan (next); + // df_insn_rescan (insn); + // df_insn_rescan (next); ++change_count; } @@ -1484,7 +1499,7 @@ opt_const_cmp_to_sub (void) * delete those insns. */ static unsigned -elim_dead_assign (void) +opt_elim_dead_assign (void) { unsigned change_count = 0; for (unsigned index = 0; index + 1 < insns.size (); ++index) @@ -1835,7 +1850,7 @@ opt_shrink_stack_frame (void) adjust += 4; } else - regs.push_back (reg); + regs.push_back (copy_reg (reg, -1)); } /* don't touch - clobbers! */ @@ -1907,7 +1922,7 @@ opt_shrink_stack_frame (void) else { /* pop */ - if (usea5 && a5offset != -4) + if (usea5) { x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); @@ -2041,8 +2056,8 @@ namespace 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ - }; + 0, //( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */ + }; class pass_bbb_optimizations : public rtl_opt_pass { @@ -2087,6 +2102,10 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { + // df_set_flags (df_LR_RUN_DCE + df_DEFER_INSN_RESCAN); + // df_note_add_problem (); + // df_analyze (); + be_verbose = strchr (string_bbb_opts, 'v'); bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); @@ -2106,7 +2125,7 @@ namespace if (do_opt_strcpy && opt_strcpy ()) done = 0, update_insns (); - if (do_commute_add_move && commute_add_move ()) + if (do_commute_add_move && opt_commute_add_move ()) done = 0, update_insns (); if (do_propagate_moves && opt_propagate_moves ()) @@ -2119,7 +2138,7 @@ namespace if (do_merge_add && opt_merge_add ()) done = 0, update_insns (), update_insn_infos (); - if (do_elim_dead_assign && elim_dead_assign ()) + if (do_elim_dead_assign && opt_elim_dead_assign ()) done = 0, update_insns (), update_insn_infos (); if (do_bb_reg_rename) From e0bc074377aadb67fd623bd92a28c6938a53c557 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 24 Apr 2017 01:07:46 +0200 Subject: [PATCH 087/303] @B fix mregparm for function pointer calls --- gcc/config/m68k/amigaos.c | 569 +++++++++++++++++++++++----------------------- 1 file changed, 280 insertions(+), 289 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index d385ab1ff108..c93188a3e90d 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -1,25 +1,25 @@ /* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 - Free Software Foundation, Inc. - Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). - Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 + Free Software Foundation, Inc. + Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). + Heavily modified by Kamil Iskra (iskra@student.uci.agh.edu.pl). -This file is part of GCC. + This file is part of GCC. -GCC 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. + GCC 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. -GCC 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. + GCC 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 GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ //work without flag_writable_strings which is not in GCC4 #define REGPARMS_68K 1 @@ -38,6 +38,7 @@ Boston, MA 02111-1307, USA. */ #include "tm_p.h" #include "target.h" #include "diagnostic-core.h" +#include "langhooks.h" #include "config/m68k/amigaos.h" //#define MYDEBUG 1 @@ -56,28 +57,28 @@ static rtx gen_stack_management_call (rtx, rtx, const char *); /* Baserel support. */ /* Does operand (which is a symbolic_operand) live in text space? If - so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. + so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. - This function is used in base relative code generation. */ + This function is used in base relative code generation. */ int read_only_operand (rtx operand) -{ - if (GET_CODE (operand) == CONST) + { + if (GET_CODE (operand) == CONST) operand = XEXP (XEXP (operand, 0), 0); - if (GET_CODE (operand) == SYMBOL_REF) + if (GET_CODE (operand) == SYMBOL_REF) return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); - return 1; -} + return 1; + } /* Choose the section to use for DECL. RELOC is true if its value contains - any relocatable expression. */ + any relocatable expression. */ void amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED, - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) -{ - // if (TREE_CODE (decl) == STRING_CST) + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) + { + // if (TREE_CODE (decl) == STRING_CST) // { //// flag_writable_strings /data_section not in gcc4, ////make life easy and put to same section @@ -104,195 +105,189 @@ amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED, // readonly_data_section (); // else //data_section (); -} + } /* This function is used while generating a base relative code. - It returns 1 if a decl is not relocatable, i. e., if it can be put - in the text section. - Currently, it's very primitive: it just checks if the object size - is less than 4 bytes (i. e., if it can hold a pointer). It also - supports arrays and floating point types. */ + It returns 1 if a decl is not relocatable, i. e., if it can be put + in the text section. + Currently, it's very primitive: it just checks if the object size + is less than 4 bytes (i. e., if it can hold a pointer). It also + supports arrays and floating point types. */ static int amigaos_put_in_text (tree decl) -{ - tree type = TREE_TYPE (decl); - if (TREE_CODE (type) == ARRAY_TYPE) + { + tree type = TREE_TYPE (decl); + if (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); - return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0 - && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32) - || FLOAT_TYPE_P (type); -} + return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0 + && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32) + || FLOAT_TYPE_P (type); + } /* Record properties of a DECL into the associated SYMBOL_REF. */ void amigaos_encode_section_info (tree decl, rtx rtl, int first) -{ - default_encode_section_info (decl, rtl, first); + { + default_encode_section_info (decl, rtl, first); - - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - else - { - if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl) - && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST - ) - || amigaos_put_in_text (decl))) - || (TREE_CODE (decl) == VAR_DECL - && DECL_SECTION_NAME (decl) != NULL)) - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - } -} + if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + else + { + if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl) + && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST + ) + || amigaos_put_in_text (decl))) + || (TREE_CODE (decl) == VAR_DECL + && DECL_SECTION_NAME (decl) != NULL)) + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + } + } /* Common routine used to check if a4 should be preserved/restored. */ int amigaos_restore_a4 (void) -{ - return (flag_pic >= 3 && - (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4 - || lookup_attribute ("saveds", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))); -} + { + return (flag_pic >= 3 && + (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4 + || lookup_attribute ("saveds", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))); + } void amigaos_alternate_pic_setup (FILE *stream) -{ - if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) + { + if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) asm_fprintf (stream, "\tjbsr %U__restore_a4\n"); - else if (lookup_attribute ("saveds", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + else if (lookup_attribute ("saveds", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n"); -} + } /* Attributes support. */ #define AMIGA_CHIP_SECTION_NAME ".datachip" /* Handle a "chip" attribute; - arguments as in struct attribute_spec.handler. */ + arguments as in struct attribute_spec.handler. */ tree amigaos_handle_decl_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - if (TREE_CODE (*node) == VAR_DECL) - { - if (is_attribute_p ("chip", name)) + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) + { + if (TREE_CODE (*node) == VAR_DECL) + { + if (is_attribute_p ("chip", name)) #ifdef TARGET_ASM_NAMED_SECTION - { - if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node)) + { + if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node)) error ("`chip' attribute cannot be specified for local variables"); - else - { - /* The decl may have already been given a section attribute from - a previous declaration. Ensure they match. */ - if (DECL_SECTION_NAME (*node) == NULL_TREE) - DECL_SECTION_NAME (*node) = - build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1, - AMIGA_CHIP_SECTION_NAME); - else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)), - AMIGA_CHIP_SECTION_NAME) != 0) - { - error_with_decl (*node, - "`chip' for `%s' conflicts with previous declaration"); - } - } - } + else + { + /* The decl may have already been given a section attribute from + a previous declaration. Ensure they match. */ + if (DECL_SECTION_NAME (*node) == NULL_TREE) + DECL_SECTION_NAME (*node) = + build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1, + AMIGA_CHIP_SECTION_NAME); + else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)), + AMIGA_CHIP_SECTION_NAME) != 0) + { + error_with_decl (*node, + "`chip' for `%s' conflicts with previous declaration"); + } + } + } #else - error ("`chip' attribute is not supported for this target"); + error ("`chip' attribute is not supported for this target"); #endif - } - else - { - warning (OPT_Wattributes, "`%s' attribute only applies to variables", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } + } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to variables", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } - return NULL_TREE; -} + return NULL_TREE; + } //----- from 68k.c start - - - - - /* Stack checking and automatic extension support. */ void amigaos_prologue_begin_hook (FILE *stream, int fsize) -{ - if (TARGET_STACKCHECK) - { - if (fsize < 256) + { + if (TARGET_STACKCHECK) + { + if (fsize < 256) asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tjra %U__stkovf\n" - "\t0:\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit"))); - else + "\tjcc 0f\n" + "\tjra %U__stkovf\n" + "\t0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__stkchk_d0\n", - fsize); - } -} + fsize); + } + } void amigaos_alternate_frame_setup_f (FILE *stream, int fsize) -{ - if (fsize < 128) + { + if (fsize < 128) asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I%d,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\tlink %Ra5,%I%d:W\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit")), - fsize, -fsize); - else + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\tlink %Ra5,%I%d:W\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n", - fsize); -} + fsize); + } void amigaos_alternate_frame_setup (FILE *stream, int fsize) -{ - if (!fsize) + { + if (!fsize) asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I0,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit"))); - else if (fsize < 128) + "\tjcc 0f\n" + "\tmoveq %I0,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else if (fsize < 128) asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I%d,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\taddw %I%d,%Rsp\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit")), - fsize, -fsize); - else + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\taddw %I%d,%Rsp\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n", - fsize); -} + fsize); + } //static rtx //gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func) @@ -385,7 +380,8 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) struct amigaos_args * cum = decl == current_function_decl ? &mycum : &othercum; *cump = decl == current_function_decl; cum->num_of_regs = amigaos_regparm > 0 ? amigaos_regparm : 0; - DPRINTF(("0amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); + DPRINTF( + ("0amigaos_init_cumulative_args %s %p -> %d\r\n", decl ? lang_hooks.decl_printable_name (decl, 2) : "?", cum, cum->num_of_regs)); /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. @@ -394,28 +390,32 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) cum->last_arg_reg = -1; cum->regs_already_used = 0; - if (decl) + if (fntype) { - tree attrs = DECL_ATTRIBUTES(decl); - if (lookup_attribute ("stkparm", attrs)) - cum->num_of_regs = 0; - else + tree attrs = decl ? DECL_ATTRIBUTES(decl) : NULL; + if (attrs) { - tree ratree = lookup_attribute ("regparm", attrs); - cum->num_of_regs = amigaos_regparm != 0 ? - amigaos_regparm : AMIGAOS_DEFAULT_REGPARM; - if (ratree) + if (lookup_attribute ("stkparm", attrs)) + cum->num_of_regs = 0; + else { - tree args = TREE_VALUE(ratree); - - if (args && TREE_CODE (args) == TREE_LIST) + tree ratree = lookup_attribute ("regparm", attrs); + cum->num_of_regs = amigaos_regparm != 0 ? + amigaos_regparm : + AMIGAOS_DEFAULT_REGPARM; + if (ratree) { - tree val = TREE_VALUE(args); - if (TREE_CODE (val) == INTEGER_CST) + tree args = TREE_VALUE(ratree); + + if (args && TREE_CODE (args) == TREE_LIST) { - int no = TREE_INT_CST_LOW(val); - if (no > 0 && no < AMIGAOS_MAX_REGPARM) - cum->num_of_regs = no; + tree val = TREE_VALUE(args); + if (TREE_CODE (val) == INTEGER_CST) + { + int no = TREE_INT_CST_LOW(val); + if (no > 0 && no < AMIGAOS_MAX_REGPARM) + cum->num_of_regs = no; + } } } } @@ -442,7 +442,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); int sz = type ? TREE_INT_CST_LOW(type) : 0; if (sz > 64) /* mark a0 as already used. */ - cum->regs_already_used |= 1<<8; + cum->regs_already_used |= 1 << 8; } } @@ -465,13 +465,12 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) /* Update the data in CUM to advance over an argument. */ void -amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, - bool) +amigaos_function_arg_advance (cumulative_args_t cum_v, machine_mode, const_tree, bool) { struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum; /* Update the data in CUM to advance over an argument. */ - DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cump)); + DPRINTF(("amigaos_function_arg_advance1 %p\r\n", cum)); if (cum->last_arg_reg != -1) { @@ -507,8 +506,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ /* FIXME: The last condition below is a workaround for a bug. */ if (TARGET_68881 && FLOAT_MODE_P(mode) && - GET_MODE_UNIT_SIZE (mode) <= 12 - && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode)) + GET_MODE_UNIT_SIZE (mode) <= 12 && (GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT || mode == SCmode)) { regbegin = 16; /* FPx */ len = GET_MODE_NUNITS(mode); @@ -534,8 +532,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ if (!(cum->regs_already_used & mask)) { int end; - for (end = reg; end < cum->num_of_regs && end < reg + len; - end++, mask <<= 1) + for (end = reg; end < cum->num_of_regs && end < reg + len; end++, mask <<= 1) if (cum->regs_already_used & mask) break; if (end == reg + len) @@ -546,7 +543,7 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ } } - if (reg == cum->num_of_regs && altregbegin != -1) + if (reg == cum->num_of_regs && altregbegin != -1) { DPRINTF(("look for alt reg\n")); regbegin = altregbegin; @@ -568,14 +565,15 @@ _m68k_function_arg (struct amigaos_args * cum, machine_mode mode, const_tree typ in a register, and which register. */ struct rtx_def * -amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, - const_tree type, bool) +amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, const_tree type, bool) { DPRINTF(("amigaos_function_arg %p\r\n", cum_v.p)); struct amigaos_args *cum = *get_cumulative_args (cum_v) ? &mycum : &othercum; - tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE; + tree asmtree = type ? TYPE_ATTRIBUTES(cum->formal_type ? TREE_VALUE(cum->formal_type) : type) : NULL_TREE; + //tree asmtree = type ? TYPE_ATTRIBUTES(type) : NULL_TREE; + if (asmtree && 0 == strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) { int i; @@ -596,18 +594,18 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, return _m68k_function_arg (cum, mode, type); } -void amiga_emit_regparm_clobbers(void) +void +amiga_emit_regparm_clobbers (void) { - rtx sp = gen_raw_REG(Pmode, 15); + rtx sp = gen_raw_REG (Pmode, 15); for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (mycum.regs_already_used & (1 << i)) { - rtx reg = gen_raw_REG(Pmode, i); - emit_insn(gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, gen_rtx_MEM(Pmode, reg)))); + rtx reg = gen_raw_REG (Pmode, i); + emit_insn (gen_rtx_CLOBBER(Pmode, gen_rtx_SET(reg, gen_rtx_MEM(Pmode, reg)))); } } - /* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, one if they are compatible, and two if they are nearly compatible (which causes a warning to be generated). */ @@ -633,8 +631,7 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2) attr2 = NULL_TREE; if (attr1 && attr2) { - if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low - != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low) + if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low) return 0; } else if (attr1 || attr2) @@ -647,140 +644,135 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2) } /* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, - one if they are compatible, and two if they are nearly compatible - (which causes a warning to be generated). */ + one if they are compatible, and two if they are nearly compatible + (which causes a warning to be generated). */ #if 0 static int m68k_comp_type_attributes (tree type1, tree type2) -{ + { - /* Functions or methods are incompatible if they specify mutually + /* Functions or methods are incompatible if they specify mutually exclusive ways of passing arguments. */ - if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) - { - tree arg1, arg2; - if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != - !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) - || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != - !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) + if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) + { + tree arg1, arg2; + if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != + !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) + || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != + !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */ - arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); - arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); - if (arg1 && arg2) - { - int num1 = 0, num2 = 0; - if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) - { - tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); - if (numofregs) + arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); + arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); + if (arg1 && arg2) + { + int num1 = 0, num2 = 0; + if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) + { + tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); + if (numofregs) num1 = TREE_INT_CST_LOW (numofregs); - } - if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) - { - tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); - if (numofregs) + } + if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) + { + tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); + if (numofregs) num2 = TREE_INT_CST_LOW (numofregs); - } - if (num1 != num2) + } + if (num1 != num2) return 0; /* Different numbers, or no number in one type. */ - } - } + } + } #ifdef TARGET_AMIGAOS return amigaos_comp_type_attributes(type1, type2); #else - return 1; + return 1; #endif -} + } #endif /* end-GG-local */ - /* Handle a "regparm", "stkparm" attribute; arguments as in struct attribute_spec.handler. */ tree -amigaos_handle_type_attribute (tree *node, tree name, tree args, - int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { tree nnn = *node; - do { // while (0); - DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn))); - if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE - || TREE_CODE (nnn) == METHOD_TYPE) - { - /* 'regparm' accepts one optional argument - number of registers in - single class that should be used to pass arguments. */ - if (is_attribute_p ("regparm", name)) + do + { // while (0); + DPRINTF(("%p with treecode %d\n", node, TREE_CODE(nnn))); + if (TREE_CODE (nnn) == FUNCTION_DECL || TREE_CODE (nnn) == FUNCTION_TYPE || TREE_CODE (nnn) == METHOD_TYPE) { - DPRINTF(("regparm found\n")); - - if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn))) - { - error ("`regparm' and `stkparm' are mutually exclusive"); - break; - } - if (args && TREE_CODE (args) == TREE_LIST) + /* 'regparm' accepts one optional argument - number of registers in + single class that should be used to pass arguments. */ + if (is_attribute_p ("regparm", name)) { - tree val = TREE_VALUE(args); - DPRINTF(("regparm with val: %d\n", TREE_CODE(val))); - if (TREE_CODE (val) == INTEGER_CST) + DPRINTF(("regparm found\n")); + + if (lookup_attribute ("stkparm", TYPE_ATTRIBUTES(nnn))) + { + error ("`regparm' and `stkparm' are mutually exclusive"); + break; + } + if (args && TREE_CODE (args) == TREE_LIST) { - int no = TREE_INT_CST_LOW(val); - if (no < 0 || no > AMIGAOS_MAX_REGPARM) + tree val = TREE_VALUE(args); + DPRINTF(("regparm with val: %d\n", TREE_CODE(val))); + if (TREE_CODE (val) == INTEGER_CST) { - error ("`regparm' attribute: value %d not in [0 - %d]", - no, - AMIGAOS_MAX_REGPARM); + int no = TREE_INT_CST_LOW(val); + if (no < 0 || no > AMIGAOS_MAX_REGPARM) + { + error ("`regparm' attribute: value %d not in [0 - %d]", no, + AMIGAOS_MAX_REGPARM); + break; + } + } + else + { + error ("invalid argument(s) to `regparm' attribute"); break; } } - else + } + else if (is_attribute_p ("stkparm", name)) + { + if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn))) { - error ("invalid argument(s) to `regparm' attribute"); + error ("`regparm' and `stkparm' are mutually exclusive"); break; } } - } - else if (is_attribute_p ("stkparm", name)) - { - if (lookup_attribute ("regparm", TYPE_ATTRIBUTES(nnn))) + else if (is_attribute_p ("stackext", name)) { - error ("`regparm' and `stkparm' are mutually exclusive"); - break; + if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn))) + { + error ("`stackext' and `interrupt' are mutually exclusive"); + break; + } } - } - else if (is_attribute_p ("stackext", name)) - { - if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES(nnn))) + else if (is_attribute_p ("saveds", name)) { - error ("`stackext' and `interrupt' are mutually exclusive"); - break; } } - else if (is_attribute_p ("saveds", name)) + else { + warning (OPT_Wattributes, "`%s' attribute only applies to functions", IDENTIFIER_POINTER(name)); } + return NULL_TREE ; } - else - { - warning (OPT_Wattributes, "`%s' attribute only applies to functions", - IDENTIFIER_POINTER(name)); - } - return NULL_TREE; - } while (0); + while (0); // error case *no_add_attrs = true; - return NULL_TREE; + return NULL_TREE ; } - extern bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); bool -amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, - int *total, bool speed) +amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed) { // DPRINTF(("outer: %d, opno: %d", outer_code, opno)); bool r = m68k_rtx_costs (x, mode, outer_code, opno, total, speed); @@ -790,13 +782,12 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, return r; } - /* Output assembly to switch to section NAME with attribute FLAGS. */ extern void amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) { - if (0 == strncmp(".text", name, 5)) + if (0 == strncmp (".text", name, 5)) name = ".text"; fprintf (asm_out_file, "\t%s\n", name); } @@ -806,7 +797,8 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U /** * Does x reference the pic_reg and is const or plus? */ -int amiga_is_const_pic_ref(const_rtx x) +int +amiga_is_const_pic_ref (const_rtx x) { const_rtx y = x; if (flag_pic < 3) @@ -816,19 +808,18 @@ int amiga_is_const_pic_ref(const_rtx x) return (x != y && REG_P(y) && REGNO(y) == PIC_REG); } - /* Does operand (which is a symbolic_operand) live in text space? If - so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. + so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. - This function is used in base relative code generation. */ + This function is used in base relative code generation. */ int read_only_operand (rtx operand) { if (GET_CODE (operand) == CONST) - operand = XEXP (XEXP (operand, 0), 0); + operand = XEXP(XEXP (operand, 0), 0); if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P(operand); return 1; } From cbc99060c9a11080a62913d87030ad33ca15ae66 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 24 Apr 2017 23:55:30 +0200 Subject: [PATCH 088/303] @B fix handling of jumps/labels in opt_reg_rename --- gcc/bbb-opts.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 14 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index d0288f254f9c..db99815fee58 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -212,7 +212,6 @@ struct insn_info _use &= ~o._def; _use |= o._use; _def = 0; - _hard &= ~_use; } inline bool @@ -339,6 +338,9 @@ copy_reg (rtx reg, int newregno) static void temp_reg_rename (std::vector > & loc, rtx x, unsigned oldregno, unsigned newregno) { + if (!x) + return; + RTX_CODE code = GET_CODE(x); const char *fmt = GET_RTX_FORMAT(code); @@ -542,6 +544,7 @@ update_insn_infos (void) if (pass && infos[pos].contains (ii)) break; + ii._hard = 0; ii |= infos[pos]; if (LABEL_P(insn)) @@ -646,7 +649,7 @@ update_insn_infos (void) use.scan (pattern); if (single_set (insn) == 0) use._hard = use._use | use._def; - + else /* if not cc0 defined check for mod. */ if (!use.is_def (FIRST_PSEUDO_REGISTER)) { @@ -684,6 +687,34 @@ bit2regno (unsigned bit) return regno; } +static unsigned +find_start (std::set & found, unsigned start, unsigned rename_regno) +{ + /* search the start. */ + while (start < 0) + { + unsigned startm1 = start - 1; + + /* already searched. */ + if (found.find (startm1) != found.end ()) + break; + + /* do not run over RETURNS */ + rtx_insn * before = insns[startm1]; + if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before))) + break; + + start = startm1; + + /* found the definition without use. */ + insn_info & jj = infos[start]; + if (jj.is_def (rename_regno) && !jj.is_use (rename_regno)) + break; + + } + return start; +} + /* * Always prefer lower register numbers within the class. */ @@ -696,10 +727,12 @@ opt_reg_rename (void) insn_info & ii = infos[index]; /* do not rename if register is hard or used in same statement. */ - const unsigned toRename = ii._def & ~ii._hard & ~ii._use; - if (!toRename) + const unsigned rename_regbit = ii._def & ~ii._hard & ~ii._use; + if (!rename_regbit) continue; + const unsigned rename_regno = bit2regno (rename_regbit); + /* get the mask for free registers. */ unsigned mask = ii.get_free_mask (); if (!mask) @@ -717,11 +750,36 @@ opt_reg_rename (void) unsigned pos = todo[todo.size () - 1]; todo.pop_back (); + /* already searched. */ if (found.find (pos) != found.end ()) continue; - if (LABEL_P(insns[pos])) + rtx_insn * insn = insns[pos]; + if (LABEL_P(insn)) { + found.insert (pos); + + /* for each jump to this label: + * check if the reg was used at that jump. + * if used, find def + */ + for (std::vector::iterator i = jumps.begin (); i != jumps.end (); ++i) + { + if (JUMP_LABEL(*i) == insn) + { + std::map::iterator j = insn2index.find (*i); + if (j == insn2index.end ()) + continue; + + unsigned start = j->second; + if (!infos[start].is_use (rename_regno)) + continue; + + start = find_start (found, start, rename_regno); + todo.push_back (start); + } + } + if (pos + 1 < insns.size ()) todo.push_back (pos + 1); continue; @@ -730,18 +788,18 @@ opt_reg_rename (void) insn_info & jj = infos[pos]; /* marked as hard reg -> invalid rename */ - if (jj._hard & toRename) + if (jj._hard & rename_regbit) mask = 0; /* defined again -> invalid rename */ - if ((jj._def & toRename) && !(jj._use & toRename)) + if ((jj._def & rename_regbit) && !(jj._use & rename_regbit)) mask = 0; if (!mask) break; /* not used. */ - if (!(jj._use & toRename)) + if (!(jj._use & rename_regbit)) continue; /* update free regs. */ @@ -753,17 +811,41 @@ opt_reg_rename (void) found.insert (pos); /* follow jump and/or next insn. */ - rtx_insn * insn = insns[pos]; if (JUMP_P(insn)) { std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); - if (j != insn2index.end ()) - todo.push_back (j->second); + if (j == insn2index.end ()) + { + /* whoops - label not found. */ + todo.clear (); + mask = 0; + break; + } + unsigned label_index = j->second; + if (found.find (label_index) == found.end ()) + { + /* if the rename_reg is used in the insn before. + * search the start. + */ + if (label_index > 0) + { + insn_info & bb = infos[label_index - 1]; + if (bb.is_use (rename_regbit)) + { + unsigned start = find_start (found, label_index - 1, rename_regno); + todo.push_back (start); + } + } + todo.push_back (label_index); + } rtx jmppattern = PATTERN (insn); if (GET_CODE(jmppattern) == PARALLEL) { - return 0; /* can't handle yet. Abort renaming. */ + /* can't handle yet. Abort renaming. */ + todo.clear (); + mask = 0; + break; } rtx jmpsrc = XEXP(jmppattern, 1); @@ -777,7 +859,7 @@ opt_reg_rename (void) if (mask) { - int oldregno = bit2regno (toRename); + int oldregno = bit2regno (rename_regbit); int newregno = bit2regno (mask); /* check the renamed insns. */ @@ -812,7 +894,8 @@ opt_reg_rename (void) if (!ok) continue; - log ("opt_reg_rename %s -> %s (%d locs)\n", reg_names[oldregno], reg_names[newregno], patch.size ()); + log ("opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], + patch.size (), index); /* apply all changes. */ for (std::vector >::iterator j = patch.begin (); j != patch.end (); ++j) From ee7031d5d1442ca1e933b3cb029f91ba1534354d Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 25 Apr 2017 11:30:06 +0200 Subject: [PATCH 089/303] @B fix regrename... --- gcc/bbb-opts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index db99815fee58..3e6c316149b0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -691,7 +691,7 @@ static unsigned find_start (std::set & found, unsigned start, unsigned rename_regno) { /* search the start. */ - while (start < 0) + while (start > 0) { unsigned startm1 = start - 1; From e550db50f02dfa9bcfdf533e664ab032fca2a235 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 25 Apr 2017 12:42:11 +0200 Subject: [PATCH 090/303] @R add target 'amigaosvasm' from https://github.com/alpine9000/gcc --- config.sub | 6 ++-- gcc/config.gcc | 10 ++++++ gcc/config/m68k/amigaos.c | 19 ++++++++++- gcc/config/m68k/m68k.c | 17 +++++++++- gcc/config/m68k/m68k.h | 78 +++++++++++++++++++++++++++++++++++++++++-- gcc/config/m68k/m68kamigaos.h | 66 ++++++++++++++++++++++++++++++++++-- 6 files changed, 185 insertions(+), 11 deletions(-) diff --git a/config.sub b/config.sub index 41146e11c6c9..35247fe0c474 100755 --- config.sub +++ config.sub @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2016-01-01' +timestamp='2017-04-21' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -500,7 +500,7 @@ case $basic_machine in amiga | amiga-*) basic_machine=m68k-unknown ;; - amigaos | amigados) + amigaos | amigaosvasm | amigados) basic_machine=m68k-unknown os=-amigaos ;; @@ -1380,7 +1380,7 @@ case $os in | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rt* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ diff --git a/gcc/config.gcc b/gcc/config.gcc index 762594c073ae..0beee32c863c 100644 --- gcc/config.gcc +++ gcc/config.gcc @@ -1936,6 +1936,16 @@ m68k-*-elf* | fido-*-elf*) ;; esac ;; +m68k*-*-amigaosvasm*) + default_m68k_cpu=68000 + tm_file="${tm_file} dbx.h newlib-stdint.h m68k/m68kamigaos.h" + tm_defines="${tm_defines} MOTOROLA=1 TARGET_AMIGAOS TARGET_AMIGAOS_VASM TARGET_CPU_DEFAULT=0" + tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-amigaos" + tm_p_file="${tm_p_file} m68k/amigaos-protos.h" + extra_objs=amigaos.o + extra_options="${extra_options} m68k/amigaos.opt" + gnu_ld=yes + ;; m68k*-*-amigaos*) default_m68k_cpu=68000 tm_file="${tm_file} dbx.h newlib-stdint.h m68k/m68kamigaos.h" diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index c93188a3e90d..27831df2d543 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -50,6 +50,7 @@ //int amiga_declare_object; + #if 0 static int amigaos_put_in_text (tree); static rtx gen_stack_management_call (rtx, rtx, const char *); @@ -783,7 +784,7 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *tota } /* Output assembly to switch to section NAME with attribute FLAGS. */ - +#ifndef TARGET_AMIGAOS_VASM extern void amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) { @@ -791,6 +792,22 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U name = ".text"; fprintf (asm_out_file, "\t%s\n", name); } +#else +extern void +amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) +{ + if (0 == strncmp(".text", name, 5)) + name = ".text"; + + if (0 == strncmp("section ", name, 8)) { +// fprintf (asm_out_file, "\t.section\t%s\n", name); + fprintf (asm_out_file, "\t%s\n", name); + } else { + fprintf (asm_out_file, "\tsection %s\n", name); + } +} +#endif + /* Baserel support. */ diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 3fabe00a678a..8a40cbc2ab1f 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -191,7 +191,11 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; #if INT_OP_GROUP == INT_OP_DOT_WORD #undef TARGET_ASM_ALIGNED_HI_OP +#ifndef TARGET_AMIGAOS_VASM #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" +#else +#define TARGET_ASM_ALIGNED_HI_OP "\tdc.w\t" +#endif #endif #if INT_OP_GROUP == INT_OP_NO_DOT @@ -595,8 +599,11 @@ m68k_option_override (void) if (!flag_pic || flag_pic > 2) { m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_JSR; - +#ifndef TARGET_AMIGAOS_VASM m68k_symbolic_jump = "jra %a0"; +#else + m68k_symbolic_jump = "jmp %a0"; +#endif } else if (TARGET_ID_SHARED_LIBRARY) /* All addresses must be loaded from the GOT. */ @@ -1831,13 +1838,21 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos && next_insn_tests_no_inequality (insn)) { cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N | CC_NO_OVERFLOW; +#ifndef TARGET_AMIGAOS_VASM return "move%.w %1,%%ccr"; +#else + return "move%.w %1,ccr"; +#endif } if (count == 2 && DATA_REG_P (operands[1]) && next_insn_tests_no_inequality (insn)) { cc_status.flags = CC_NOT_NEGATIVE | CC_INVERTED | CC_NO_OVERFLOW; +#ifndef TARGET_AMIGAOS_VASM return "move%.w %1,%%ccr"; +#else + return "move%.w %1,ccr"; +#endif } /* count == 1 followed by bvc/bvs and count == 0 followed by bcc/bcs are also possible, but need diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 5142adf24e4d..200f07ef63a4 100644 --- gcc/config/m68k/m68k.h +++ gcc/config/m68k/m68k.h @@ -204,7 +204,11 @@ along with GCC; see the file COPYING3. If not see #define INT_OP_DC 3 /* dc.b, dc.w, dc.l */ /* Set the default. */ +#ifndef TARGET_AMIGAOS_VASM #define INT_OP_GROUP INT_OP_DOT_WORD +#else +#define INT_OP_GROUP INT_OP_DC +#endif /* Bit values used by m68k-devices.def to identify processor capabilities. */ #define FL_BITFIELD (1 << 0) /* Support bitfield instructions. */ @@ -729,9 +733,49 @@ do { if (cc_prev_status.flags & CC_IN_68881) \ if (cc_prev_status.flags & CC_NO_OVERFLOW) \ return NO_OV; \ return NORMAL; } while (0) + +#ifdef TARGET_AMIGAOS_VASM +#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \ + do { \ + FILE *_hide_asm_out_file = (MYFILE); \ + const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \ + int _hide_thissize = (MYLENGTH); \ + { \ + FILE *asm_out_file = _hide_asm_out_file; \ + const unsigned char *p = _hide_p; \ + int thissize = _hide_thissize; \ + int i; \ + fprintf (asm_out_file, "\tdc.b \""); \ + \ + for (i = 0; i < thissize; i++) \ + { \ + int c = p[i]; \ + if (c == '\"' || c == '\\') \ + putc ('\\', asm_out_file); \ + if (ISPRINT (c)) \ + putc (c, asm_out_file); \ + else \ + { \ + fprintf (asm_out_file, "\\%o", c); \ + /* After an octal-escape, if a digit follows, \ + terminate one string constant and start another. \ + The VAX assembler fails to stop reading the escape \ + after three digits, so this is the only way we \ + can get it to parse the data properly. */ \ + if (i < thissize - 1 && ISDIGIT (p[i + 1])) \ + fprintf (asm_out_file, "\"\n\tdc.b \""); \ + } \ + } \ + fprintf (asm_out_file, "\"\n"); \ + } \ + } \ + while (0) +#endif + /* Control the assembler format that we output. */ +#ifndef TARGET_AMIGAOS_VASM #define ASM_APP_ON "#APP\n" #define ASM_APP_OFF "#NO_APP\n" #define TEXT_SECTION_ASM_OP "\t.text" @@ -741,6 +785,17 @@ do { if (cc_prev_status.flags & CC_IN_68881) \ #define LOCAL_LABEL_PREFIX "" #define USER_LABEL_PREFIX "_" #define IMMEDIATE_PREFIX "#" +#else +#define ASM_APP_ON "" +#define ASM_APP_OFF "" +#define TEXT_SECTION_ASM_OP "\tsection .text" +#define DATA_SECTION_ASM_OP "\tsection .data" +#define GLOBAL_ASM_OP "\txdef\t" +#define REGISTER_PREFIX "" +#define LOCAL_LABEL_PREFIX "_." +#define USER_LABEL_PREFIX "_" +#define IMMEDIATE_PREFIX "#" +#endif #define REGISTER_NAMES \ {REGISTER_PREFIX"d0", REGISTER_PREFIX"d1", REGISTER_PREFIX"d2", \ @@ -860,11 +915,17 @@ do { if (cc_prev_status.flags & CC_IN_68881) \ /* The m68k does not use absolute case-vectors, but we must define this macro anyway. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ +#ifndef TARGET_AMIGAOS_VASM +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ asm_fprintf (FILE, "\t.long %LL%d\n", VALUE) - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ asm_fprintf (FILE, "\t.word %LL%d-%LL%d\n", VALUE, REL) +#else +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + asm_fprintf (FILE, "\tdc.l %LL%d\n", VALUE) +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL) +#endif /* We don't have a way to align to more than a two-byte boundary, so do the best we can and don't complain. */ @@ -874,13 +935,24 @@ do { if (cc_prev_status.flags & CC_IN_68881) \ #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN /* Use "move.l %a4,%a4" to advance within code. */ +#ifndef TARGET_AMIGAOS_VASM #define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG) \ if ((LOG) > 0) \ fprintf ((FILE), "\t.balignw %u,0x284c\n", 1 << (LOG)); #endif +#else +#define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG) \ + if ((LOG) > 0) \ + fprintf ((FILE), "\tcnop 0,%u\n", 1 << (LOG)); +#endif +#ifndef TARGET_AMIGAOS_VASM #define ASM_OUTPUT_SKIP(FILE,SIZE) \ fprintf (FILE, "\t.skip %u\n", (int)(SIZE)) +#else +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\tds.b %u\n", (int)(SIZE)) +#endif #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ( fputs (".comm ", (FILE)), \ diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 20e0b66face2..3ca2cd666e7c 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -61,7 +61,11 @@ along with GCC; see the file COPYING3. If not see These labels will not appear in the symbol table. */ #undef LOCAL_LABEL_PREFIX +#ifndef TARGET_AMIGAOS_VASM #define LOCAL_LABEL_PREFIX "." +#else +#define LOCAL_LABEL_PREFIX "_." +#endif /* The prefix to add to user-visible assembler symbols. */ @@ -71,24 +75,43 @@ along with GCC; see the file COPYING3. If not see /* config/m68k.md has an explicit reference to the program counter, prefix this by the register prefix. */ +#ifndef TARGET_AMIGAOS_VASM #define ASM_RETURN_CASE_JUMP \ do { \ return "jmp %%pc@(2,%0:w)"; \ } while (0) +#else +#define ASM_RETURN_CASE_JUMP \ + do { \ + return "jmp (2,pc,%0.w)"; \ + } while (0) +#endif /* This is how to output an assembler line that says to advance the location counter to a multiple of 2**LOG bytes. */ +#ifndef TARGET_AMIGAOS_VASM #ifndef ALIGN_ASM_OP #define ALIGN_ASM_OP "\t.align\t" #endif +#else +#define ALIGN_ASM_OP "\talign\t" +#endif #undef ASM_OUTPUT_ALIGN +#ifndef TARGET_AMIGAOS_VASM #define ASM_OUTPUT_ALIGN(FILE,LOG) \ do { \ if ((LOG) > 0) \ fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \ } while (0) +#else +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ +do { \ + if ((LOG) > 0) \ + fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, (LOG)); \ +} while (0) +#endif #if 0 extern int amiga_declare_object; @@ -126,7 +149,11 @@ amiga_declare_object = 0 #undef M68K_STATIC_CHAIN_REG_NAME #define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a1" +#ifndef TARGET_AMIGAOS_VASM +#define ASM_COMMENT_START "|" +#else #define ASM_COMMENT_START "|" +#endif /* Define how the m68k registers should be numbered for Dwarf output. The numbering provided here should be compatible with the native @@ -147,15 +174,34 @@ amiga_declare_object = 0 #undef ASM_OUTPUT_COMMON #undef ASM_OUTPUT_LOCAL -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +#ifndef TARGET_AMIGAOS_VASM +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ( fputs (".comm ", (FILE)), \ assemble_name ((FILE), (NAME)), \ fprintf ((FILE), ",%u\n", (int)(SIZE))) +#else +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ + ( switch_to_section (bss_section), \ + fputs ("|.comm\n\tcnop 0,4\n", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ":\n\tds.b %u\n", (int)(SIZE)), \ + fputs ("\txdef ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), "\n")) +#endif +#ifndef TARGET_AMIGAOS_VASM #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ( fputs (".lcomm ", (FILE)), \ assemble_name ((FILE), (NAME)), \ fprintf ((FILE), ",%u\n", (int)(SIZE))) +#else +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +( switch_to_section (bss_section), \ + fputs ("|.lcomm\n\tcnop 0,4\n", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ":\n\tds.b %u\n", (int)(SIZE))) +#endif /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to keep switch tables in the text section. */ @@ -169,9 +215,13 @@ amiga_declare_object = 0 fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); /* end of stuff from m68kv4.h */ +#ifndef TARGET_AMIGAOS_VASM #ifndef BSS_SECTION_ASM_OP #define BSS_SECTION_ASM_OP "\t.bss" #endif +#else +#define BSS_SECTION_ASM_OP "\tsection\tbss" +#endif #ifndef ASM_OUTPUT_ALIGNED_BSS #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ @@ -294,8 +344,13 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ /* Various -m flags require special flags to the assembler. */ #undef ASM_SPEC +#ifndef TARGET_AMIGAOS_VASM +#define ASM_SPEC \ + "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" +#else #define ASM_SPEC \ - "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" + "-gas -esc -ldots -Fhunk -quiet %(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" +#endif #undef ASM_CPU_SPEC #define ASM_CPU_SPEC \ @@ -305,8 +360,13 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{m68040} " \ "%{m68060}" +#ifndef TARGET_AMIGAOS_VASM #define ASM_CPU_DEFAULT_SPEC \ - "%{!m680*:%{!mc680*:-m68040}}" + "%{!m680*:%{!mc680*:-m68040}}" +#else +#define ASM_CPU_DEFAULT_SPEC \ + "%{!m680*:%{!mc680*:-m68000}}" +#endif /* Choose the right startup file, depending on whether we use base relative code, base relative code with automatic relocation (-resident), their From c48a0f72eefe8e3a45b24184fc75e5a93eaabfc2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 25 Apr 2017 19:37:45 +0200 Subject: [PATCH 091/303] @B renaming is better again, test cases stil ok --- gcc/bbb-opts.c | 163 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 82 insertions(+), 81 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 3e6c316149b0..407e2f74fd9f 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -738,123 +738,124 @@ opt_reg_rename (void) if (!mask) continue; - std::set found; + /* first = pos to start, second indicates to treat def as use. */ std::vector todo; + std::set found; if (index + 1 < insns.size ()) todo.push_back (index + 1); +// /* trigger jump checking */ +// if (index > 0 && LABEL_P(insns[index - 1])) +// todo.push_back (std::make_pair(index - 1, 0)); + found.insert (index); /* a register was defined, follow all branches. */ - while (todo.size ()) + while (mask && todo.size ()) { - unsigned pos = todo[todo.size () - 1]; + unsigned runpos = todo[todo.size () - 1]; todo.pop_back (); - /* already searched. */ - if (found.find (pos) != found.end ()) - continue; - - rtx_insn * insn = insns[pos]; - if (LABEL_P(insn)) + for (unsigned pos = runpos; mask && pos < insns.size (); ++pos) { - found.insert (pos); + /* already searched. */ + if (found.find (pos) != found.end ()) + break; - /* for each jump to this label: - * check if the reg was used at that jump. - * if used, find def - */ - for (std::vector::iterator i = jumps.begin (); i != jumps.end (); ++i) + rtx_insn * insn = insns[pos]; + if (LABEL_P(insn)) { - if (JUMP_LABEL(*i) == insn) + found.insert (pos); + + /* for each jump to this label: + * check if the reg was used at that jump. + * if used, find def + */ + for (std::vector::iterator i = jumps.begin (); i != jumps.end (); ++i) { - std::map::iterator j = insn2index.find (*i); - if (j == insn2index.end ()) - continue; + if (JUMP_LABEL(*i) == insn) + { + std::map::iterator j = insn2index.find (*i); + if (j == insn2index.end ()) + continue; - unsigned start = j->second; - if (!infos[start].is_use (rename_regno)) - continue; + unsigned start = j->second; + if (!infos[start].is_use (rename_regno)) + continue; - start = find_start (found, start, rename_regno); - todo.push_back (start); + start = find_start (found, start, rename_regno); + todo.push_back (start); + } } + continue; } - if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); - continue; - } + insn_info & jj = infos[pos]; - insn_info & jj = infos[pos]; + /* marked as hard reg -> invalid rename */ + if (jj._use & jj._hard & rename_regbit) + mask = 0; - /* marked as hard reg -> invalid rename */ - if (jj._hard & rename_regbit) - mask = 0; +// /* defined again -> invalid rename */ +// if ((jj._def & rename_regbit) && !(jj._use & rename_regbit)) +// mask = 0; - /* defined again -> invalid rename */ - if ((jj._def & rename_regbit) && !(jj._use & rename_regbit)) - mask = 0; - - if (!mask) - break; + if (!mask) + break; - /* not used. */ - if (!(jj._use & rename_regbit)) - continue; + /* not used. and not a def */ + if (pos == runpos && (jj._def & rename_regbit)) + { + /* continue since this pos was added by start search. */ + } + else if (!(jj._use & rename_regbit)) + break; - /* update free regs. */ - mask &= ~jj._use; - mask &= ~jj._def; - if (!mask) - break; + /* update free regs. */ + mask &= ~jj._use; + mask &= ~jj._def; + if (!mask) + break; - found.insert (pos); + found.insert (pos); - /* follow jump and/or next insn. */ - if (JUMP_P(insn)) - { - std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); - if (j == insn2index.end ()) + /* follow jump and/or next insn. */ + if (JUMP_P(insn)) { - /* whoops - label not found. */ - todo.clear (); - mask = 0; - break; - } + std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); + if (j == insn2index.end ()) + { + /* whoops - label not found. */ + mask = 0; + break; + } - unsigned label_index = j->second; - if (found.find (label_index) == found.end ()) - { - /* if the rename_reg is used in the insn before. - * search the start. - */ - if (label_index > 0) + unsigned label_index = j->second; + if (found.find (label_index) == found.end ()) { - insn_info & bb = infos[label_index - 1]; + /* if the rename_reg is used in the insn before. + * search the start. + */ + insn_info & bb = infos[label_index + 1]; if (bb.is_use (rename_regbit)) { unsigned start = find_start (found, label_index - 1, rename_regno); todo.push_back (start); } + todo.push_back (label_index + 1); + } + rtx jmppattern = PATTERN (insn); + if (GET_CODE(jmppattern) == PARALLEL) + { + /* can't handle yet. Abort renaming. */ + mask = 0; + break; } - todo.push_back (label_index); - } - rtx jmppattern = PATTERN (insn); - if (GET_CODE(jmppattern) == PARALLEL) - { - /* can't handle yet. Abort renaming. */ - todo.clear (); - mask = 0; - break; - } - rtx jmpsrc = XEXP(jmppattern, 1); - if (jmpsrc && GET_CODE(jmpsrc) == IF_THEN_ELSE) - if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); + rtx jmpsrc = XEXP(jmppattern, 1); + if (!jmpsrc || GET_CODE(jmpsrc) != IF_THEN_ELSE) + break; + } } - else if (pos + 1 < insns.size ()) - todo.push_back (pos + 1); } if (mask) From 50dc4c0949e49397d6c6de28207d34cbf137621c Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 26 Apr 2017 10:34:16 +0200 Subject: [PATCH 092/303] @B fix backward search at labels --- gcc/bbb-opts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 407e2f74fd9f..78eb0cc32f38 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -836,7 +836,7 @@ opt_reg_rename (void) * search the start. */ insn_info & bb = infos[label_index + 1]; - if (bb.is_use (rename_regbit)) + if (bb.is_use (rename_regno)) { unsigned start = find_start (found, label_index - 1, rename_regno); todo.push_back (start); From ec53abb40b3066d74243c566ea7528ac1bd0f150 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 26 Apr 2017 11:43:37 +0200 Subject: [PATCH 093/303] @I no longer using df functions to determine reg use. @B fixed propagate moves, @B fixed eliminate dead assignments --- gcc/bbb-opts.c | 278 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 149 insertions(+), 129 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 78eb0cc32f38..9d138063fb27 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -58,7 +58,6 @@ #include "backend.h" #include "target.h" #include "rtl.h" -#include "df.h" #include "tm_p.h" #include "insn-config.h" #include "recog.h" @@ -242,6 +241,9 @@ struct insn_info return true; } + void + scan_call (rtx_insn *); + void scan (rtx); @@ -267,6 +269,31 @@ struct insn_info } }; +void +insn_info::scan_call (rtx_insn * insn) +{ + /* add mregparm registers. */ + for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1)) + { + rtx op, reg; + + if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) + for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) + use (r); + } + /* also mark all registers as not renamable */ + _hard = _use; + + scan (PATTERN (insn)); + + /* mark scratch registers. */ + def (0); + def (1); + def (8); + def (9); + +} + /* scan rtx for registers and set the corresponding flags. */ void insn_info::scan (rtx x) @@ -478,8 +505,6 @@ update_insns () rtx_insn *insn, *next; clear (); - // df_insn_rescan_all (); - char inproepilogue = 1; /* create a vector with relevant insn. */ for (insn = get_insns (); insn; insn = next) @@ -567,26 +592,7 @@ update_insn_infos (void) if (CALL_P(insn)) { insn_info use; - - /* add mregparm registers. */ - for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1)) - { - rtx op, reg; - - if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) - for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) - use.use (r); - } - /* also mark all registers as not renamable */ - use._hard = use._use; - - use.scan (pattern); - - /* mark scratch registers. */ - use.def (0); - use.def (1); - use.def (8); - use.def (9); + use.scan_call (insn); infos[pos] = use | ii; ii.updateWith (use); @@ -687,6 +693,27 @@ bit2regno (unsigned bit) return regno; } +/* check if that register is touched between from and to, excluding from and to .*/ +static bool +is_reg_touched_between (unsigned regno, int from, int to) +{ + for (int index = from + 1; index < to; ++index) + { + insn_info ii; + rtx_insn * insn = insns[index]; + if (CALL_P(insn)) + ii.scan_call (insn); + else + ii.scan (PATTERN (insn)); + if (ii.is_use (regno) || ii.is_def (regno)) + return true; + } + return false; +} + +/* + * search backward and find the initial assignment for that regno. + */ static unsigned find_start (std::set & found, unsigned start, unsigned rename_regno) { @@ -1045,47 +1072,76 @@ opt_propagate_moves () if (rtx_equal_p (srci, dstj) && rtx_equal_p (srcj, dsti)) { /* Ensure correct usage. */ - if (!reg_used_between_p (srci, current_label, ii) && !reg_used_between_p (srci, ii, jj) - && !reg_used_between_p (srci, jj, insn) && !reg_used_between_p (dsti, current_label, ii) - && !reg_used_between_p (dsti, jj, insn)) + if (is_reg_touched_between (REGNO(srci), current_label_index, *i) // label ... move src,x + || is_reg_touched_between (REGNO(srci), *i, *j) // move src,x ... move x,src + || is_reg_touched_between (REGNO(srci), *j, index) // move x,src ... jcc + || is_reg_touched_between (REGNO(dsti), *j, index) // label ... move src,x + || is_reg_touched_between (REGNO(dsti), *j, index) // move x,src ... jcc + ) + { + ++j; + continue; + } + + std::vector fixups; + + /* if there are jumps out of the loop, + * check if the modification occurs before the jump, + * and if, that it's a plus const. + */ + if (jump_out.size ()) { - std::vector fixups; + std::vector::iterator label_iter = jump_out.begin (); + int fixup = 0; - /* if there are jumps out of the loop, - * check if the modification occurs before the jump, - * and if, that it's a plus const. - */ - if (jump_out.size ()) + for (unsigned k = *i + 1; k != *j; ++k) { - std::vector::iterator label_iter = jump_out.begin (); - int fixup = 0; + rtx_insn * check = insns[k]; + if (JUMP_P(check)) + { + fixups.push_back (fixup); + if (++label_iter == jump_out.end ()) + break; + continue; + } - for (unsigned k = *i + 1; k != *j; ++k) + if (reg_overlap_mentioned_p (dsti, PATTERN (check))) { - rtx_insn * check = insns[k]; - if (JUMP_P(check)) + /* right now only support auto_incs. */ + rtx set = single_set (check); + rtx src = SET_SRC(set); + rtx dst = SET_DEST(set); + + if (reg_overlap_mentioned_p (dsti, dst)) { - fixups.push_back (fixup); - if (++label_iter == jump_out.end ()) + if (REG_P(dst)) + break; + if (!MEM_P(dst)) + break; + + rtx x = XEXP(dst, 0); + if (GET_CODE(x) == REG) + fixup += 0; // direct use + else if (GET_CODE(x) == PRE_INC || + GET_CODE(x) == POST_INC) + fixup -= GET_MODE_SIZE(GET_MODE(dst)); + else if (GET_CODE(dst) == PRE_DEC || + GET_CODE(dst) == POST_DEC) + fixup += GET_MODE_SIZE(GET_MODE(dst)); + else break; - continue; } - if (reg_overlap_mentioned_p (dsti, PATTERN (check))) + if (reg_overlap_mentioned_p (dsti, src)) { - /* right now only support auto_incs. */ - rtx set = single_set (check); - rtx src = SET_SRC(set); - rtx dst = SET_DEST(set); - - if (reg_overlap_mentioned_p (dsti, dst)) + if (REG_P(src)) + fixup += 0; + else { - if (REG_P(dst)) - break; - if (!MEM_P(dst)) + if (!MEM_P(src)) break; - rtx x = XEXP(dst, 0); + rtx x = XEXP(src, 0); if (GET_CODE(x) == REG) fixup += 0; // direct use else if (GET_CODE(x) == PRE_INC || @@ -1097,91 +1153,64 @@ opt_propagate_moves () else break; } - - if (reg_overlap_mentioned_p (dsti, src)) - { - if (REG_P(src)) - fixup += 0; - else - { - if (!MEM_P(src)) - break; - - rtx x = XEXP(src, 0); - if (GET_CODE(x) == REG) - fixup += 0; // direct use - else if (GET_CODE(x) == PRE_INC || - GET_CODE(x) == POST_INC) - fixup -= GET_MODE_SIZE(GET_MODE(dst)); - else if (GET_CODE(dst) == PRE_DEC || - GET_CODE(dst) == POST_DEC) - fixup += GET_MODE_SIZE(GET_MODE(dst)); - else - break; - } - } } } } + } - /* got a fixup for all jump_outs? */ - if (fixups.size () == jump_out.size ()) - { - rtx_insn * before = insns[current_label_index - 1]; - rtx_insn * after = insns[index + 1]; - rtx bset = single_set (before); + /* got a fixup for all jump_outs? */ + if (fixups.size () == jump_out.size ()) + { + rtx_insn * before = insns[current_label_index - 1]; + rtx_insn * after = insns[index + 1]; + rtx bset = single_set (before); - log ("propagate_moves condition met, moving regs %s, %s\n", - reg_names[REGNO(srci)], - reg_names[REGNO(dsti)]); + log ("propagate_moves condition met, moving regs %s, %s\n", + reg_names[REGNO(srci)], + reg_names[REGNO(dsti)]); - /* Move in front of loop and mark as dead. */ - rtx_insn * newii = make_insn_raw (PATTERN (ii)); - SET_INSN_DELETED(ii); + /* Move in front of loop and mark as dead. */ + rtx_insn * newii = make_insn_raw (PATTERN (ii)); + SET_INSN_DELETED(ii); - /* Plus check if the reg was just loaded. */ - if (bset) + /* Plus check if the reg was just loaded. */ + if (bset) + { + rtx bdst = SET_DEST(bset); + if (REG_P(bdst) && REGNO(bdst) == REGNO(srci)) { - rtx bdst = SET_DEST(bset); - if (REG_P(bdst) && REGNO(bdst) == REGNO(srci)) - { - SET_SRC(PATTERN(newii)) = SET_SRC(bset); + SET_SRC(PATTERN(newii)) = SET_SRC(bset); // SET_INSN_DELETED(ii); - } } - else - add_reg_note (newii, REG_DEAD, srci); + } + else + add_reg_note (newii, REG_DEAD, srci); - add_insn_after (newii, before, 0); + add_insn_after (newii, before, 0); - /* Move behind loop - into next BB. */ - rtx_insn * newjj = make_insn_raw (PATTERN (jj)); - add_insn_before (newjj, after, 0); - SET_INSN_DELETED(jj); + /* Move behind loop - into next BB. */ + rtx_insn * newjj = make_insn_raw (PATTERN (jj)); + add_insn_before (newjj, after, 0); + SET_INSN_DELETED(jj); - reg_reg.erase (j); - reg_reg.erase (i); - j = reg_reg.end (); - inc = false; + reg_reg.erase (j); + reg_reg.erase (i); + j = reg_reg.end (); + inc = false; - // df_insn_rescan (newii); - // df_insn_rescan (newjj); + /* add fixes if there were jumps out of the loop. */ + if (jump_out.size ()) + { + log ("propagate_moves fixing %d jump outs\n", jump_out.size ()); - /* add fixes if there were jumps out of the loop. */ - if (jump_out.size ()) + for (unsigned k = 0; k < jump_out.size (); ++k) { - log ("propagate_moves fixing %d jump outs\n", jump_out.size ()); - - for (unsigned k = 0; k < jump_out.size (); ++k) - { - rtx neu = gen_rtx_SET( - dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k]))); - rtx_insn * neui = emit_insn_after (neu, jump_out[k]); - // df_insn_rescan (neui); - } + rtx neu = gen_rtx_SET( + dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k]))); + rtx_insn * neui = emit_insn_after (neu, jump_out[k]); } - ++change_count; } + ++change_count; } } if (inc) @@ -1277,8 +1306,6 @@ opt_strcpy () SET_INSN_DELETED(x2reg); SET_INSN_DELETED(insn); - // df_insn_rescan (reg2x); - ++change_count; } } @@ -1394,9 +1421,6 @@ opt_commute_add_move (void) add_reg_note (next, REG_INC, reg1dst); - // df_insn_rescan (insn); - // df_insn_rescan (next); - ++change_count; } } @@ -1579,14 +1603,14 @@ opt_const_cmp_to_sub (void) } /* - * Some optimizations (e.g. propagate_moves) might result into an unuses assignment behind the loop. + * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop. * delete those insns. */ static unsigned opt_elim_dead_assign (void) { unsigned change_count = 0; - for (unsigned index = 0; index + 1 < insns.size (); ++index) + for (int index = insns.size () - 1; index >= 0; --index) { rtx_insn * insn = insns[index]; if (!NONJUMP_INSN_P(insn)) @@ -2186,10 +2210,6 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { - // df_set_flags (df_LR_RUN_DCE + df_DEFER_INSN_RESCAN); - // df_note_add_problem (); - // df_analyze (); - be_verbose = strchr (string_bbb_opts, 'v'); bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); From b02fdbd28177c393c37b5de2448b1a9506a14f82 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 26 Apr 2017 17:50:10 +0200 Subject: [PATCH 094/303] @B fixed opt_const_cmp_to_sub --- gcc/bbb-opts.c | 81 ++++++++++++++++++++++++---------------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9d138063fb27..f0e2f7b58d4c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1491,8 +1491,8 @@ opt_const_cmp_to_sub (void) if (!setp) continue; - rtx dstp = SET_DEST(setp); - if (!REG_P(dstp)) + rtx constant_reg = SET_DEST(setp); + if (!REG_P(constant_reg)) continue; rtx srcp = SET_SRC(setp); @@ -1503,34 +1503,20 @@ opt_const_cmp_to_sub (void) if (intval < -8 || intval > 7 || intval == 0) continue; - enum machine_mode mode = GET_MODE(dstp); + enum machine_mode mode = GET_MODE(constant_reg); if (GET_MODE_SIZE(mode) > 4) continue; // printf("mode size: %d\n", GET_MODE_SIZE(mode)); - rtx reg = dstp == left ? right : left; - rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval)); - - rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus)); + rtx reg = constant_reg == left ? right : constant_reg == right ? left : 0; - int num_clobbers_to_add = 0; - int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add); - if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev))) + // no gain with address regs. + if (!reg || REGNO(reg) > 7) continue; - // also convert current statement to cmp #0, reg - SET_INSN_DELETED(insn); - rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copy_reg(reg, -1), gen_rtx_CONST_INT(mode, 0))); - insn = emit_insn_after (neu, prev); - add_reg_note (insn, REG_DEAD, reg); - - SET_INSN_DELETED(prev); - prev = emit_insn_before (PATTERN (neuprev), insn); - - log ("const_cmp_to_sub replaced reg-reg compare with sub\n"); - - if (dstp != left) + // search the jump(s) + bool ok = true; { // invert all conditions using this statement. std::vector todo; @@ -1538,7 +1524,7 @@ opt_const_cmp_to_sub (void) done.resize (insns.size ()); todo.push_back (index + 1); - while (todo.size ()) + while (ok && todo.size ()) { unsigned pos = todo[todo.size () - 1]; todo.pop_back (); @@ -1555,7 +1541,7 @@ opt_const_cmp_to_sub (void) todo.push_back (pos + 1); rtx_insn * patchme = insns[pos]; - if (!JUMP_P(insn)) + if (!JUMP_P(patchme)) continue; std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme)); @@ -1569,32 +1555,33 @@ opt_const_cmp_to_sub (void) { rtx condition = XEXP(jmpsrc, 0); RTX_CODE code = GET_CODE(condition); - RTX_CODE newcode = code; - if (code == GE) - newcode = LE; - else if (code == GT) - newcode = LT; - else if (code == LT) - newcode = GT; - else if (code == LE) - newcode = GE; - else if (code == GEU) - newcode = LEU; - else if (code == GTU) - newcode = LTU; - else if (code == LTU) - newcode = GTU; - else if (code == LEU) - newcode = GEU; - - if (code != newcode) - { - log ("patch jcc %d -> %d\n", code, newcode); - XEXP(jmpsrc, 0) = gen_rtx_fmt_ee(newcode, VOIDmode, XEXP(condition, 0), XEXP(condition, 1)); - } + ok = code == EQ || code == NE; } } } + if (!ok) + continue; + + rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval)); + + rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus)); + + int num_clobbers_to_add = 0; + int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add); + if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev))) + continue; + + // also convert current statement to cmp #0, reg + SET_INSN_DELETED(insn); + rtx copyreg = copy_reg (reg, -1); + rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copyreg, gen_rtx_CONST_INT(mode, 0))); + insn = emit_insn_after (neu, prev); + add_reg_note (insn, REG_DEAD, copyreg); + + SET_INSN_DELETED(prev); + prev = emit_insn_before (PATTERN (neuprev), insn); + + log ("const_cmp_to_sub replaced reg-reg compare with sub\n"); ++change_count; } From 67cc3de981f1498e225257ccd4783452e127e58c Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 26 Apr 2017 20:21:59 +0200 Subject: [PATCH 095/303] @B fix NPE --- gcc/bbb-opts.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f0e2f7b58d4c..ceb548bea823 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1551,7 +1551,9 @@ opt_const_cmp_to_sub (void) rtx jmppattern = PATTERN (patchme); rtx jmpsrc = XEXP(jmppattern, 1); - if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + if (!jmpsrc) + ok = false; + else if (GET_CODE(jmpsrc) == IF_THEN_ELSE) { rtx condition = XEXP(jmpsrc, 0); RTX_CODE code = GET_CODE(condition); From 17dff22094612ae1f122eec1dad72583a677c1e3 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 27 Apr 2017 17:25:51 +0200 Subject: [PATCH 096/303] @R some better encapsulation, @D add reg usage to asm source use 'V' --- gcc/bbb-opts.c | 421 +++++++++++++++++++++++++++++++++++---------------------- gcc/final.c | 7 + 2 files changed, 264 insertions(+), 164 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ceb548bea823..32b1aed86ae5 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -66,14 +66,17 @@ #include "tree.h" #include "tree-pass.h" #include "conditions.h" -#include "cselib.h" #include "langhooks.h" #include #include #include -static bool be_verbose; +bool be_very_verbose; +bool be_verbose; +#ifdef __ECLIPSE__ +extern char * string_bbb_opts; +#endif extern struct lang_hooks lang_hooks; /* Lookup of the current function name. */ @@ -116,86 +119,102 @@ log (char const * fmt, ...) * * Track use & def separate to determine starting points. */ -struct insn_info +class insn_info { - unsigned _use; // bit set if registers are used - unsigned _def; // bit set if registers are defined - unsigned _hard; // bit set if registers can't be renamed - - insn_info () : - _use (0), _def (0), _hard (0) + rtx_insn * insn; // the insn + unsigned myuse; // bit set if registers are used in this statement + unsigned mydef; // bit set if registers are set in this statement + unsigned hard; // bit set if registers can't be renamed + unsigned use; // bit set if registers are used in program flow + unsigned def; // bit set if registers are defined in program flow + +public: + insn_info (rtx_insn * i = 0) : + insn (i), myuse (0), mydef (0), hard (0), use (0), def (0) { } inline void reset () { - _use = 0; - _def = 0; - _hard = 0; + use = 0; + def = 0; + hard = 0; + } + + inline bool + is_empty () + { + return !def && !use && !hard; } inline void - use (int regno) + mark_use (int regno) { - _use |= 1 << regno; + myuse |= 1 << regno; + use |= 1 << regno; } inline void - def (int regno) + mark_def (int regno) { - _def |= 1 << regno; + mydef |= 1 << regno; + def |= 1 << regno; } inline void - hard (int regno) + mark_hard (int regno) { - _hard |= 1 << regno; + hard |= 1 << regno; } inline void unset (int regno) { - _use &= ~(1 << regno); - _def &= ~(1 << regno); - _hard &= ~(1 << regno); + use &= ~(1 << regno); + def &= ~(1 << regno); + hard &= ~(1 << regno); + } + + inline unsigned + get_use () const + { + return use; + } + inline unsigned + get_def () const + { + return def; + } + inline unsigned + get_hard () const + { + return hard; } inline bool is_use (int regno) { - return (_use & (1 << regno)) != 0; + return (use & (1 << regno)) != 0; } inline bool is_def (int regno) { - return (_def & (1 << regno)) != 0; + return (def & (1 << regno)) != 0; } inline bool is_hard (int regno) { - return (_hard & (1 << regno)) != 0; - } - - inline insn_info - operator | (insn_info const & o) const - { - insn_info t; - t._use = _use | o._use; - t._def = _def | o._def; - t._hard = _hard | o._hard; - return t; + return (hard & (1 << regno)) != 0; } - inline insn_info & - operator |= (insn_info const & o) + inline void + clear_hard_def () { - _use |= o._use; - _def |= o._def; - _hard |= o._hard; - return *this; + hard = 0; + def = 0; } /* @@ -208,106 +227,155 @@ struct insn_info inline void updateWith (insn_info const & o) { - _use &= ~o._def; - _use |= o._use; - _def = 0; + use &= ~o.def; + use |= o.use; + def = 0; } - inline bool - operator == (insn_info const & o) + inline insn_info & + merge (insn_info const & o) { - return _use == o._use; + use = (use & ~o.def) | o.use; + def |= o.def; + hard |= o.hard; + return *this; + } + + inline insn_info & + drop_def () + { + use &= ~def; + return *this; } +#if 0 + inline insn_info + operator | (insn_info const & o) const + { + insn_info t; + t.use = use | o.use; + t.def = def | o.def; + t.hard = hard | o.hard; + return t; + } + + inline bool + operator == (insn_info const & o) + { + return use == o.use; + } + inline insn_info operator ~ () const + { + insn_info t; + t.use = ~use; + t.def = ~def; + t.hard = ~hard; + return t; + } +#endif + + inline insn_info & + make_hard () + { + hard = use | def; + return *this; + } + + inline insn_info & + make_clobber () { - insn_info t; - t._use = ~_use; - t._def = ~_def; - t._hard = ~_hard; - return t; + hard = use = def = use | def; + return *this; } inline bool contains (insn_info const & o) const { - if (o._def & ~_def) + if (o.def & ~def) return false; - if (o._use & ~_use) + if (o.use & ~use) return false; - if (o._hard & ~_hard) + if (o.hard & ~hard) return false; return true; } void - scan_call (rtx_insn *); + scan (); void - scan (rtx); + scan_rtx (rtx); /* return bits for alternate free registers. */ unsigned get_free_mask () const { - if (_def & _hard) + if (def & hard) return 0; - if (!_def || _def > 0x1000) + if (!def || def > 0x1000) return 0; - unsigned mask = _def - 1; + unsigned mask = def - 1; /* more than one register -> don't touch. */ - if ((mask & ~_def) != mask) + if ((mask & ~def) != mask) return 0; - if (_def > 0xff) + if (def > 0xff) mask &= 0xff00; - return mask & ~_use; + return mask & ~use; + } + + unsigned + get_regbit () const + { + return def & ~hard & ~use & 0x7fff; } }; void -insn_info::scan_call (rtx_insn * insn) +insn_info::scan () { - /* add mregparm registers. */ - for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1)) + rtx pattern = PATTERN (insn); + if (CALL_P(insn)) { - rtx op, reg; + /* add mregparm registers. */ + for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1)) + { + rtx op, reg; - if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) - for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) - use (r); + if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) + for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) + mark_use (r); + } + /* mark scratch registers. */ + mark_def (0); + mark_def (1); + mark_def (8); + mark_def (9); + /* also mark all registers as not renamable */ + hard = use; } - /* also mark all registers as not renamable */ - _hard = _use; - - scan (PATTERN (insn)); - - /* mark scratch registers. */ - def (0); - def (1); - def (8); - def (9); - + scan_rtx (pattern); } /* scan rtx for registers and set the corresponding flags. */ void -insn_info::scan (rtx x) +insn_info::scan_rtx (rtx x) { if (REG_P(x)) { for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r) - use (r); + mark_use (r); return; } if (x == cc0_rtx) { - use (FIRST_PSEUDO_REGISTER); + mark_use (FIRST_PSEUDO_REGISTER); return; } @@ -316,17 +384,17 @@ insn_info::scan (rtx x) /* handle SET and record use and def. */ if (code == SET) { - unsigned u = _use; - scan (SET_DEST(x)); + unsigned u = use; + scan_rtx (SET_DEST(x)); if (REG_P(SET_DEST(x))) { - _def |= _use; - _use = u; + def |= use; + use = u; } - scan (SET_SRC(x)); + scan_rtx (SET_SRC(x)); int code = GET_CODE(SET_SRC(x)); if (code == ASM_OPERANDS) - _use = _hard |= _def | _use; + use = hard |= def | use; return; } @@ -334,10 +402,10 @@ insn_info::scan (rtx x) for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - scan (XEXP(x, i)); + scan_rtx (XEXP(x, i)); else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - scan (XVECEXP(x, i, j)); + scan_rtx (XVECEXP(x, i, j)); } } @@ -429,7 +497,7 @@ is_reg_dead (unsigned regno, unsigned _pos) { insn_info & ii0 = infos[pos]; // skip entries without info - if (!ii0._def && !ii0._use && !ii0._hard) + if (ii0.is_empty ()) continue; // not dead if usage is reported in the next statement @@ -438,6 +506,45 @@ is_reg_dead (unsigned regno, unsigned _pos) return true; } +/* helper stuff to enhance the asm output. */ +int my_flag_regusage; +void +append_reg_usage (FILE * f, rtx_insn * insn) +{ + + auto i = insn2index.find (insn); + if (i == insn2index.end ()) + return; + + insn_info & ii = infos[i->second]; + + fprintf (f, "\n\t\t\t\t\t\t| "); + + for (int j = 0; j < 8; ++j) + if (ii.is_use (j) || ii.is_def (j)) + { + fprintf (f, ii.is_hard (j) ? "!" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); + fprintf (f, "d%d ", j); + } + else + fprintf (f, " "); + + for (int j = 8; j < 16; ++j) + if (ii.is_use (j) || ii.is_def (j)) + { + fprintf (f, ii.is_hard (j) ? "!" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); + fprintf (f, "a%d ", j - 8); + } + else + fprintf (f, " "); + + if (ii.is_use (FIRST_PSEUDO_REGISTER)) + fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); + +} + /* * Helper function to dump the code. * Sometimes used during debugging. @@ -456,33 +563,7 @@ dump_insns (char const * name, bool all) fprintf (stderr, "%d: ", i); if (i < infos.size ()) - { - insn_info & ii = infos[i]; - - for (int j = 0; j < 8; ++j) - if (ii.is_use (j) || ii.is_def (j)) - { - if (ii.is_hard (j)) - fprintf (stderr, "!"); - if (ii.is_def (j)) - fprintf (stderr, "*"); - fprintf (stderr, "d%d ", j); - } - - for (int j = 8; j < 16; ++j) - if (ii.is_use (j) || ii.is_def (j)) - { - if (ii.is_hard (j)) - fprintf (stderr, "!"); - if (ii.is_def (j)) - fprintf (stderr, "*"); - fprintf (stderr, "a%d ", j - 8); - } - - if (ii.is_use (FIRST_PSEUDO_REGISTER)) - fprintf (stderr, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); - - } + append_reg_usage (stderr, insns[i]); fprintf (stderr, "\t"); debug_rtx (insns[i]); @@ -569,8 +650,8 @@ update_insn_infos (void) if (pass && infos[pos].contains (ii)) break; - ii._hard = 0; - ii |= infos[pos]; + ii.clear_hard_def (); + ii.merge (infos[pos]); if (LABEL_P(insn)) { @@ -591,10 +672,11 @@ update_insn_infos (void) if (CALL_P(insn)) { - insn_info use; - use.scan_call (insn); + insn_info use (insn); + use.scan (); - infos[pos] = use | ii; + ii.merge (use); + infos[pos] = ii; ii.updateWith (use); continue; @@ -602,7 +684,7 @@ update_insn_infos (void) if (JUMP_P(insn)) { - insn_info use; + insn_info use (insn); if (ANY_RETURN_P(pattern)) { tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); @@ -610,19 +692,20 @@ update_insn_infos (void) // log ("return size %d\n", sz); if (sz <= 64) { - use.hard (0); - use.use (0); + use.mark_hard (0); + use.mark_use (0); if (sz > 32) { - use.hard (1); - use.use (1); + use.mark_hard (1); + use.mark_use (1); } } ii.reset (); } - use.scan (pattern); - infos[pos] = use | ii; + use.scan (); + ii.merge (use); + infos[pos] = ii; ii.updateWith (use); continue; @@ -630,31 +713,41 @@ update_insn_infos (void) if (GET_CODE (pattern) == USE) { - rtx x = XEXP(pattern, 0); - if (REG_P(x)) - { - ii.use (REGNO(x)); - ii.hard (REGNO(x)); - } + insn_info use (insn); + use.scan (); + use.make_clobber (); + + ii.merge (use); infos[pos] = ii; + ii.updateWith (use); + +// rtx x = XEXP(pattern, 0); +// if (REG_P(x)) +// { +// ii.mark_use (REGNO(x)); +// ii.mark_hard (REGNO(x)); +// } +// infos[pos] = ii; continue; } if (GET_CODE (pattern) == CLOBBER) { /* mark regs as use and def */ - insn_info use; - use.scan (pattern); - use._hard = use._use = use._def = use._use | use._def; - infos[pos] = use | ii; + insn_info use (insn); + use.scan (); + use.make_clobber (); + ii.merge (use); + infos[pos] = ii; ii.updateWith (use); continue; } - insn_info use; - use.scan (pattern); + insn_info use (insn); + use.scan (); + if (single_set (insn) == 0) - use._hard = use._use | use._def; + use.make_hard (); else /* if not cc0 defined check for mod. */ if (!use.is_def (FIRST_PSEUDO_REGISTER)) @@ -662,15 +755,15 @@ update_insn_infos (void) CC_STATUS_INIT; NOTICE_UPDATE_CC(PATTERN (insn), insn); if (cc_status.value1 || cc_status.value2) - use.def (FIRST_PSEUDO_REGISTER); + use.mark_def (FIRST_PSEUDO_REGISTER); } /* mark not renameable in prologue/epilogue. */ if (proepilogue[pos]) - use._hard = use._use | use._def; + use.make_hard (); - ii._use &= ~use._def; - infos[pos] = use | ii; + ii.merge (use); + infos[pos] = ii; ii.updateWith (use); } ++pass; @@ -699,12 +792,12 @@ is_reg_touched_between (unsigned regno, int from, int to) { for (int index = from + 1; index < to; ++index) { - insn_info ii; rtx_insn * insn = insns[index]; + insn_info ii (insn); if (CALL_P(insn)) - ii.scan_call (insn); + ii.scan (); else - ii.scan (PATTERN (insn)); + ii.scan_rtx (PATTERN (insn)); if (ii.is_use (regno) || ii.is_def (regno)) return true; } @@ -754,7 +847,7 @@ opt_reg_rename (void) insn_info & ii = infos[index]; /* do not rename if register is hard or used in same statement. */ - const unsigned rename_regbit = ii._def & ~ii._hard & ~ii._use; + const unsigned rename_regbit = ii.get_regbit (); if (!rename_regbit) continue; @@ -819,7 +912,7 @@ opt_reg_rename (void) insn_info & jj = infos[pos]; /* marked as hard reg -> invalid rename */ - if (jj._use & jj._hard & rename_regbit) + if (jj.get_use () & jj.get_hard () & rename_regbit) mask = 0; // /* defined again -> invalid rename */ @@ -830,16 +923,16 @@ opt_reg_rename (void) break; /* not used. and not a def */ - if (pos == runpos && (jj._def & rename_regbit)) + if (pos == runpos && (jj.get_def () & rename_regbit)) { /* continue since this pos was added by start search. */ } - else if (!(jj._use & rename_regbit)) + else if (!(jj.get_use () & rename_regbit)) break; /* update free regs. */ - mask &= ~jj._use; - mask &= ~jj._def; + mask &= ~jj.get_use (); + mask &= ~jj.get_def (); if (!mask) break; @@ -1616,7 +1709,7 @@ opt_elim_dead_assign (void) if (is_reg_dead (REGNO(dst), index)) { - log ("elim_dead_assign to %s\n", reg_names[REGNO(dst)]); + log ("%d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); ++change_count; } @@ -1897,9 +1990,9 @@ opt_shrink_stack_frame (void) continue; insn_info & jj = infos[i]; - ii |= jj; + ii.merge (jj); } - unsigned freemask = ~ii._use; + unsigned freemask = ~ii.get_use (); rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM); rtx a5 = gen_raw_REG (SImode, FRAME_POINTER_REGNUM); @@ -2123,9 +2216,9 @@ opt_shrink_stack_frame (void) continue; insn_info & jj = infos[i]; - ii |= jj; + ii.merge (jj); } - unsigned freemask = ~ii._use; + unsigned freemask = ~ii.get_use (); if (freemask & (1 << FRAME_POINTER_REGNUM)) { @@ -2199,7 +2292,8 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { - be_verbose = strchr (string_bbb_opts, 'v'); + be_very_verbose = strchr (string_bbb_opts, 'V'); + be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v'); bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); @@ -2257,7 +2351,6 @@ namespace if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) dump_insns ("bbb", strchr (string_bbb_opts, 'X')); - clear (); return 0; } diff --git a/gcc/final.c b/gcc/final.c index 31f9b4815d75..94c96470e019 100644 --- gcc/final.c +++ gcc/final.c @@ -2151,6 +2151,7 @@ call_from_call_insn (rtx_call_insn *insn) SEEN is used to track the end of the prologue, for emitting debug information. We force the emission of a line note after both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG. */ +rtx_insn * current_insn; rtx_insn * final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, @@ -2160,6 +2161,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, rtx set; #endif rtx_insn *next; + current_insn = insn; insn_counter++; @@ -3622,6 +3624,8 @@ do_assembler_dialects (const char *p, int *dialect) void output_asm_insn (const char *templ, rtx *operands) { + extern bool be_very_verbose; + extern void append_reg_usage(FILE *, rtx_insn *); const char *p; int c; #ifdef ASSEMBLER_DIALECT @@ -3778,6 +3782,9 @@ output_asm_insn (const char *templ, rtx *operands) putc (c, asm_out_file); } + if (be_very_verbose) + append_reg_usage(asm_out_file, current_insn); + /* Write out the variable names for operands, if we know them. */ if (flag_verbose_asm) output_asm_operand_names (operands, oporder, ops); From c61d5d9c3e2f1376ab8f4a9783a1fc5e9c283f3c Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 27 Apr 2017 22:27:45 +0200 Subject: [PATCH 097/303] @R some better encapsulation --- gcc/bbb-opts.c | 136 ++++++++++++++++++--------------------------------------- 1 file changed, 43 insertions(+), 93 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 32b1aed86ae5..439223bf6f87 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -123,14 +123,13 @@ class insn_info { rtx_insn * insn; // the insn unsigned myuse; // bit set if registers are used in this statement - unsigned mydef; // bit set if registers are set in this statement unsigned hard; // bit set if registers can't be renamed unsigned use; // bit set if registers are used in program flow - unsigned def; // bit set if registers are defined in program flow + unsigned def; // bit set if registers are defined here public: insn_info (rtx_insn * i = 0) : - insn (i), myuse (0), mydef (0), hard (0), use (0), def (0) + insn (i), myuse (0), hard (0), use (0), def (0) { } @@ -158,7 +157,6 @@ class insn_info inline void mark_def (int regno) { - mydef |= 1 << regno; def |= 1 << regno; } @@ -198,6 +196,12 @@ class insn_info return (use & (1 << regno)) != 0; } + inline bool + is_myuse (int regno) + { + return (myuse & (1 << regno)) != 0; + } + inline bool is_def (int regno) { @@ -340,7 +344,23 @@ void insn_info::scan () { rtx pattern = PATTERN (insn); - if (CALL_P(insn)) + if (ANY_RETURN_P(pattern)) + { + tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); + int sz = type ? TREE_INT_CST_LOW(type) : 0; + // log ("return size %d\n", sz); + if (sz <= 64) + { + mark_hard (0); + mark_use (0); + if (sz > 32) + { + mark_hard (1); + mark_use (1); + } + } + } + else if (CALL_P(insn)) { /* add mregparm registers. */ for (rtx link = CALL_INSN_FUNCTION_USAGE(insn); link; link = XEXP(link, 1)) @@ -385,11 +405,13 @@ insn_info::scan_rtx (rtx x) if (code == SET) { unsigned u = use; + unsigned mu = myuse; scan_rtx (SET_DEST(x)); if (REG_P(SET_DEST(x))) { def |= use; use = u; + myuse = mu; } scan_rtx (SET_SRC(x)); int code = GET_CODE(SET_SRC(x)); @@ -518,13 +540,14 @@ append_reg_usage (FILE * f, rtx_insn * insn) insn_info & ii = infos[i->second]; - fprintf (f, "\n\t\t\t\t\t\t| "); + if (f != stderr) + fprintf (f, "\n\t\t\t\t\t\t| "); for (int j = 0; j < 8; ++j) if (ii.is_use (j) || ii.is_def (j)) { fprintf (f, ii.is_hard (j) ? "!" : " "); - fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); fprintf (f, "d%d ", j); } else @@ -534,14 +557,14 @@ append_reg_usage (FILE * f, rtx_insn * insn) if (ii.is_use (j) || ii.is_def (j)) { fprintf (f, ii.is_hard (j) ? "!" : " "); - fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); fprintf (f, "a%d ", j - 8); } else fprintf (f, " "); if (ii.is_use (FIRST_PSEUDO_REGISTER)) - fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "*cc " : "cc "); + fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "+cc " : " cc "); } @@ -669,84 +692,24 @@ update_insn_infos (void) } rtx pattern = PATTERN (insn); + insn_info use (insn); + use.scan (); if (CALL_P(insn)) { - insn_info use (insn); - use.scan (); - - ii.merge (use); - infos[pos] = ii; - ii.updateWith (use); - - continue; } - - if (JUMP_P(insn)) + else if (JUMP_P(insn)) { - insn_info use (insn); if (ANY_RETURN_P(pattern)) { - tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); - int sz = type ? TREE_INT_CST_LOW(type) : 0; - // log ("return size %d\n", sz); - if (sz <= 64) - { - use.mark_hard (0); - use.mark_use (0); - if (sz > 32) - { - use.mark_hard (1); - use.mark_use (1); - } - } ii.reset (); } - - use.scan (); - ii.merge (use); - infos[pos] = ii; - ii.updateWith (use); - - continue; } - - if (GET_CODE (pattern) == USE) - { - insn_info use (insn); - use.scan (); - use.make_clobber (); - - ii.merge (use); - infos[pos] = ii; - ii.updateWith (use); - -// rtx x = XEXP(pattern, 0); -// if (REG_P(x)) -// { -// ii.mark_use (REGNO(x)); -// ii.mark_hard (REGNO(x)); -// } -// infos[pos] = ii; - continue; - } - - if (GET_CODE (pattern) == CLOBBER) + else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER) { - /* mark regs as use and def */ - insn_info use (insn); - use.scan (); use.make_clobber (); - ii.merge (use); - infos[pos] = ii; - ii.updateWith (use); - continue; } - - insn_info use (insn); - use.scan (); - - if (single_set (insn) == 0) + else if (single_set (insn) == 0) use.make_hard (); else /* if not cc0 defined check for mod. */ @@ -792,13 +755,8 @@ is_reg_touched_between (unsigned regno, int from, int to) { for (int index = from + 1; index < to; ++index) { - rtx_insn * insn = insns[index]; - insn_info ii (insn); - if (CALL_P(insn)) - ii.scan (); - else - ii.scan_rtx (PATTERN (insn)); - if (ii.is_use (regno) || ii.is_def (regno)) + insn_info & ii = infos[index]; + if (ii.is_myuse (regno) || ii.is_def (regno)) return true; } return false; @@ -864,10 +822,6 @@ opt_reg_rename (void) if (index + 1 < insns.size ()) todo.push_back (index + 1); -// /* trigger jump checking */ -// if (index > 0 && LABEL_P(insns[index - 1])) -// todo.push_back (std::make_pair(index - 1, 0)); - found.insert (index); /* a register was defined, follow all branches. */ while (mask && todo.size ()) @@ -913,14 +867,10 @@ opt_reg_rename (void) /* marked as hard reg -> invalid rename */ if (jj.get_use () & jj.get_hard () & rename_regbit) - mask = 0; - -// /* defined again -> invalid rename */ -// if ((jj._def & rename_regbit) && !(jj._use & rename_regbit)) -// mask = 0; - - if (!mask) - break; + { + mask = 0; + break; + } /* not used. and not a def */ if (pos == runpos && (jj.get_def () & rename_regbit)) From 63bb3cbeae6aa5780413e18a8bfe23873dc310f5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 27 Apr 2017 23:00:26 +0200 Subject: [PATCH 098/303] @R some better encapsulation --- gcc/bbb-opts.c | 228 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 120 insertions(+), 108 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 439223bf6f87..fc4acc87a0a9 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -126,11 +126,50 @@ class insn_info unsigned hard; // bit set if registers can't be renamed unsigned use; // bit set if registers are used in program flow unsigned def; // bit set if registers are defined here + int proepi; // 1 = in prologue, 2 = in epilogue, 0 = other + bool stack; // part of stack frame insns + + insn_info & + operator = (insn_info const &); public: - insn_info (rtx_insn * i = 0) : - insn (i), myuse (0), hard (0), use (0), def (0) + insn_info (rtx_insn * i = 0, int p = 0) : + insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false) + { + } + + /* update usage. */ + void + update (insn_info & o) + { + myuse = o.myuse; + hard = o.hard; + use = o.use; + def = o.def; + } + + inline rtx_insn * + get_insn () const + { + return insn; + } + + void + mark_stack () + { + stack = true; + } + + bool + is_stack () const + { + return stack; + } + + inline int + in_proepi () const { + return proepi; } inline void @@ -487,12 +526,9 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr /* * Collect some data. */ -static std::vector insns; -static std::vector proepilogue; -static std::vector temp; +static std::vector infos; static std::vector jumps; static std::map insn2index; -static std::vector infos; /* * Reset collected data. @@ -500,8 +536,6 @@ static std::vector infos; static void clear (void) { - insns.clear (); - proepilogue.clear (); jumps.clear (); insn2index.clear (); infos.clear (); @@ -578,23 +612,24 @@ dump_insns (char const * name, bool all) fprintf (stderr, "====================================: %s\n", name); if (all) { - for (rtx_insn * insn = get_insns (); insn && insn != insns[0]; insn = NEXT_INSN (insn)) + for (rtx_insn * insn = get_insns (); insn && insn != infos[0].get_insn (); insn = NEXT_INSN (insn)) debug_rtx (insn); } - for (unsigned i = 0; i < insns.size (); ++i) + for (unsigned i = 0; i < infos.size (); ++i) { fprintf (stderr, "%d: ", i); + rtx_insn * insn = infos[i].get_insn (); if (i < infos.size ()) - append_reg_usage (stderr, insns[i]); + append_reg_usage (stderr, insn); fprintf (stderr, "\t"); - debug_rtx (insns[i]); + debug_rtx (insn); if (all) { - rtx_insn * p = i + 1 < insns.size () ? insns[i + 1] : 0; - for (rtx_insn * q = NEXT_INSN (insns[i]); q && q != p; q = NEXT_INSN (q)) + rtx_insn * p = i + 1 < infos.size () ? infos[i + 1].get_insn () : 0; + for (rtx_insn * q = NEXT_INSN (insn); q && q != p; q = NEXT_INSN (q)) debug_rtx (q); } } @@ -620,9 +655,8 @@ update_insns () if (JUMP_P(insn)) jumps.push_back (insn); - insn2index.insert (std::make_pair (insn, insns.size ())); - insns.push_back (insn); - proepilogue.push_back (inproepilogue); + insn2index.insert (std::make_pair (insn, infos.size ())); + infos.push_back (insn_info (insn, inproepilogue)); if (JUMP_P(insn)) inproepilogue = 0; @@ -647,12 +681,9 @@ update_insns () static void update_insn_infos (void) { - /* prepare insn_info */ - infos.resize (insns.size ()); - /* own analyze reg life */ std::vector > todo; - todo.push_back (std::make_pair (insns.size () - 1, insn_info ())); + todo.push_back (std::make_pair (infos.size () - 1, insn_info ())); int pass = 0; while (!todo.empty ()) @@ -664,7 +695,7 @@ update_insn_infos (void) for (int pos = p.first; pos >= 0; --pos) { - rtx_insn * insn = insns[pos]; + rtx_insn * insn = infos[pos].get_insn (); /* can be NULL as used in opt_shrink_stack_frame(). */ if (!insn) continue; @@ -679,7 +710,7 @@ update_insn_infos (void) if (LABEL_P(insn)) { /* work on all jumps referring to that label. */ - for (std::vector::iterator i = jumps.begin (); i != jumps.end (); ++i) + for (auto i = jumps.begin (); i != jumps.end (); ++i) { if (JUMP_LABEL(*i) == insn) { @@ -722,11 +753,11 @@ update_insn_infos (void) } /* mark not renameable in prologue/epilogue. */ - if (proepilogue[pos]) + if (infos[pos].in_proepi ()) use.make_hard (); ii.merge (use); - infos[pos] = ii; + infos[pos].update (ii); ii.updateWith (use); } ++pass; @@ -778,7 +809,7 @@ find_start (std::set & found, unsigned start, unsigned rename_regno) break; /* do not run over RETURNS */ - rtx_insn * before = insns[startm1]; + rtx_insn * before = infos[startm1].get_insn (); if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before))) break; @@ -800,7 +831,7 @@ static unsigned opt_reg_rename (void) { // dump_insns ("rename", 1); - for (unsigned index = 0; index < insns.size (); ++index) + for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; @@ -819,7 +850,7 @@ opt_reg_rename (void) /* first = pos to start, second indicates to treat def as use. */ std::vector todo; std::set found; - if (index + 1 < insns.size ()) + if (index + 1 < infos.size ()) todo.push_back (index + 1); found.insert (index); @@ -829,13 +860,13 @@ opt_reg_rename (void) unsigned runpos = todo[todo.size () - 1]; todo.pop_back (); - for (unsigned pos = runpos; mask && pos < insns.size (); ++pos) + for (unsigned pos = runpos; mask && pos < infos.size (); ++pos) { /* already searched. */ if (found.find (pos) != found.end ()) break; - rtx_insn * insn = insns[pos]; + rtx_insn * insn = infos[pos].get_insn (); if (LABEL_P(insn)) { found.insert (pos); @@ -844,7 +875,7 @@ opt_reg_rename (void) * check if the reg was used at that jump. * if used, find def */ - for (std::vector::iterator i = jumps.begin (); i != jumps.end (); ++i) + for (auto i = jumps.begin (); i != jumps.end (); ++i) { if (JUMP_LABEL(*i) == insn) { @@ -940,7 +971,7 @@ opt_reg_rename (void) for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) { - rtx_insn * insn = insns[*i]; + rtx_insn * insn = infos[*i].get_insn (); /* temp rename. */ temp_reg_rename (locs, PATTERN (insn), oldregno, newregno); @@ -1044,9 +1075,9 @@ opt_propagate_moves () std::vector jump_out; /* start at 1 since there must be an insn before the label. */ - for (unsigned index = 1; index < insns.size (); ++index) + for (unsigned index = 1; index < infos.size (); ++index) { - rtx_insn * insn = insns[index]; + rtx_insn * insn = infos[index].get_insn (); if (LABEL_P(insn)) { @@ -1103,11 +1134,11 @@ opt_propagate_moves () bool inc = true; for (std::vector::iterator j = i + 1; j != reg_reg.end ();) { - rtx_insn * ii = insns[*i]; + rtx_insn * ii = infos[*i].get_insn (); rtx seti = single_set (ii); rtx srci = SET_SRC(seti); rtx dsti = SET_DEST(seti); - rtx_insn * jj = insns[*j]; + rtx_insn * jj = infos[*j].get_insn (); rtx setj = single_set (jj); rtx srcj = SET_SRC(setj); rtx dstj = SET_DEST(setj); @@ -1139,7 +1170,7 @@ opt_propagate_moves () for (unsigned k = *i + 1; k != *j; ++k) { - rtx_insn * check = insns[k]; + rtx_insn * check = infos[k].get_insn (); if (JUMP_P(check)) { fixups.push_back (fixup); @@ -1204,8 +1235,8 @@ opt_propagate_moves () /* got a fixup for all jump_outs? */ if (fixups.size () == jump_out.size ()) { - rtx_insn * before = insns[current_label_index - 1]; - rtx_insn * after = insns[index + 1]; + rtx_insn * before = infos[current_label_index - 1].get_insn (); + rtx_insn * after = infos[index + 1].get_insn (); rtx bset = single_set (before); log ("propagate_moves condition met, moving regs %s, %s\n", @@ -1250,7 +1281,7 @@ opt_propagate_moves () { rtx neu = gen_rtx_SET( dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k]))); - rtx_insn * neui = emit_insn_after (neu, jump_out[k]); + emit_insn_after (neu, jump_out[k]); } } ++change_count; @@ -1290,9 +1321,9 @@ opt_strcpy () rtx_insn * reg2x; unsigned int regno; - for (unsigned index = 0; index < insns.size (); ++index) + for (unsigned index = 0; index < infos.size (); ++index) { - rtx_insn * insn = insns[index]; + rtx_insn * insn = infos[index].get_insn (); if (!NONJUMP_INSN_P(insn)) { @@ -1411,9 +1442,9 @@ opt_commute_add_move (void) { unsigned change_count = 0; - for (unsigned index = 0; index + 1 < insns.size (); ++index) + for (unsigned index = 0; index + 1 < infos.size (); ++index) { - rtx_insn * insn = insns[index]; + rtx_insn * insn = infos[index].get_insn (); rtx set = single_set (insn); if (!set) continue; @@ -1434,7 +1465,7 @@ opt_commute_add_move (void) if (!CONST_INT_P(cnst)) continue; - rtx_insn * next = insns[index + 1]; + rtx_insn * next = infos[index + 1].get_insn (); rtx set2 = single_set (next); if (!set2) continue; @@ -1498,9 +1529,9 @@ opt_const_cmp_to_sub (void) { unsigned change_count = 0; #if HAVE_cc0 - for (int index = insns.size () - 2; index > 0; --index) + for (int index = infos.size () - 2; index > 0; --index) { - rtx_insn * insn = insns[index]; + rtx_insn * insn = infos[index].get_insn (); rtx seti = single_set (insn); if (!seti) continue; @@ -1529,7 +1560,7 @@ opt_const_cmp_to_sub (void) continue; // maybe add a search? - rtx_insn * prev = insns[index - 1]; + rtx_insn * prev = infos[index - 1].get_insn (); rtx setp = single_set (prev); if (!setp) continue; @@ -1564,7 +1595,7 @@ opt_const_cmp_to_sub (void) // invert all conditions using this statement. std::vector todo; std::vector done; - done.resize (insns.size ()); + done.resize (infos.size ()); todo.push_back (index + 1); while (ok && todo.size ()) @@ -1583,7 +1614,7 @@ opt_const_cmp_to_sub (void) if (pos + 1 < infos.size ()) todo.push_back (pos + 1); - rtx_insn * patchme = insns[pos]; + rtx_insn * patchme = infos[pos].get_insn (); if (!JUMP_P(patchme)) continue; @@ -1642,9 +1673,9 @@ static unsigned opt_elim_dead_assign (void) { unsigned change_count = 0; - for (int index = insns.size () - 1; index >= 0; --index) + for (int index = infos.size () - 1; index >= 0; --index) { - rtx_insn * insn = insns[index]; + rtx_insn * insn = infos[index].get_insn (); if (!NONJUMP_INSN_P(insn)) continue; @@ -1681,11 +1712,11 @@ static unsigned opt_merge_add (void) { unsigned change_count = 0; - for (unsigned index = 0; index + 2 < insns.size (); ++index) + for (unsigned index = 0; index + 2 < infos.size (); ++index) { - rtx_insn * ins1 = insns[index]; - rtx_insn * ins2 = insns[index + 1]; - rtx_insn * ins3 = insns[index + 2]; + rtx_insn * ins1 = infos[index].get_insn (); + rtx_insn * ins2 = infos[index + 1].get_insn (); + rtx_insn * ins3 = infos[index + 2].get_insn (); if (!NONJUMP_INSN_P(ins1) && !NONJUMP_INSN_P(ins2) && !NONJUMP_INSN_P(ins3)) continue; @@ -1738,17 +1769,6 @@ opt_merge_add (void) return change_count; } -/* - * Move the insns back from temp to insns. - */ -static void -clear_temp () -{ - for (unsigned i = 0; i < temp.size (); ++i) - if (temp[i]) - insns[i] = temp[i], temp[i] = 0; -} - /** * 1. scan for all used registers. * 2. scan the stack from for omittable push/pop @@ -1775,14 +1795,13 @@ static unsigned opt_shrink_stack_frame (void) { /* nothing to do. */ - if (!insns.size ()) + if (!infos.size ()) return 0; std::vector a5pos; - temp.resize (insns.size ()); unsigned pos = 0; - rtx_insn * insn = insns[pos]; + rtx_insn * insn = infos[pos].get_insn (); if (JUMP_P(insn)) /* return -> empty function*/ return 0; @@ -1794,11 +1813,12 @@ opt_shrink_stack_frame (void) * Move prologue to temp. * Only register push and parallel insn unless its a link a5 are moved. */ - for (; pos < insns.size ();) + for (; pos < infos.size ();) { - insn = insns[pos]; + insn_info & ii = infos[pos]; + insn = ii.get_insn (); - if (proepilogue[pos] != 1) + if (ii.in_proepi () != 1) break; rtx pattern = PATTERN (insn); @@ -1817,8 +1837,7 @@ opt_shrink_stack_frame (void) else { /* use movem */ - temp[pos] = insn; - insns[pos] = 0; + ii.mark_stack (); } ++pos; continue; @@ -1845,8 +1864,7 @@ opt_shrink_stack_frame (void) rtx reg = XEXP(predec, 0); if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM) { - temp[pos] = insn; - insns[pos] = 0; + ii.mark_stack (); } } } @@ -1860,9 +1878,8 @@ opt_shrink_stack_frame (void) paramstart -= INTVAL(cx); } - if (++pos >= insns.size ()) + if (++pos >= infos.size ()) { - clear_temp (); return 0; } } @@ -1873,20 +1890,21 @@ opt_shrink_stack_frame (void) unsigned prologueend = pos; /* search epilogues - there can be multiple epilogues. */ - while (pos < insns.size ()) + while (pos < infos.size ()) { - while (pos < insns.size ()) + while (pos < infos.size ()) { - if (proepilogue[pos]) + if (infos[pos].in_proepi ()) break; ++pos; } /* move epilogues away. */ - for (; pos < insns.size (); ++pos) + for (; pos < infos.size (); ++pos) { - insn = insns[pos]; - if (JUMP_P(insn) || LABEL_P(insn) || !proepilogue[pos]) + insn_info & ii = infos[pos]; + insn = ii.get_insn (); + if (JUMP_P(insn) || LABEL_P(insn) || !ii.in_proepi ()) break; /* omit the frame pointer a5. */ @@ -1903,8 +1921,7 @@ opt_shrink_stack_frame (void) } /* movem. */ - temp[pos] = insn; - insns[pos] = 0; + ii.mark_stack (); } else if (GET_CODE(pattern) == SET) { @@ -1920,10 +1937,7 @@ opt_shrink_stack_frame (void) { rtx reg = XEXP(postinc, 0); if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM) - { - temp[pos] = insn; - insns[pos] = 0; - } + ii.mark_stack (); } } } @@ -1936,10 +1950,10 @@ opt_shrink_stack_frame (void) insn_info ii; for (unsigned i = 0; i < infos.size (); ++i) { - if (proepilogue[i]) + insn_info & jj = infos[i]; + if (jj.is_stack ()) continue; - insn_info & jj = infos[i]; ii.merge (jj); } unsigned freemask = ~ii.get_use (); @@ -1949,12 +1963,13 @@ opt_shrink_stack_frame (void) unsigned adjust = 0; /* now all push/pop insns are in temp. */ - for (unsigned i = 0; i < temp.size (); ++i) + for (unsigned i = 0; i < infos.size (); ++i) { - insn = temp[i]; - if (!insn) + insn_info & ii = infos[i]; + if (!ii.is_stack ()) continue; + insn = ii.get_insn (); rtx pattern = PATTERN (insn); /* check the pushed regs, either a vector or single statements */ if (GET_CODE(pattern) == PARALLEL) @@ -2119,9 +2134,10 @@ opt_shrink_stack_frame (void) /* fix sp offsets. */ if (!usea5 && adjust) { - for (unsigned index = 0; index < insns.size (); ++index) + for (unsigned index = 0; index < infos.size (); ++index) { - insn = insns[index]; + insn_info & ii = infos[index]; + insn = ii.get_insn (); if (!insn || !INSN_P(insn)) continue; @@ -2155,17 +2171,16 @@ opt_shrink_stack_frame (void) { for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) { - temp[*i] = insns[*i]; - insns[*i] = 0; + insn_info & ii = infos[*i]; + ii.mark_stack (); } - update_insn_infos (); - insn_info ii; for (unsigned i = 0; i < infos.size (); ++i) { - if (proepilogue[i]) + insn_info ii; + insn_info & jj = infos[i]; + if (jj.is_stack ()) continue; - insn_info & jj = infos[i]; ii.merge (jj); } unsigned freemask = ~ii.get_use (); @@ -2174,13 +2189,10 @@ opt_shrink_stack_frame (void) { log ("dropping unused frame pointer\n"); for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) - SET_INSN_DELETED(temp[*i]); + SET_INSN_DELETED(infos[*i].get_insn ()); } } - /* restore stack insns */ - clear_temp (); - return 0; } From a882cc15bab5a29c566ccda41663549d87cb0be3 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 28 Apr 2017 11:39:49 +0200 Subject: [PATCH 099/303] @R optimize opt_merge_add --- gcc/bbb-opts.c | 370 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 287 insertions(+), 83 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index fc4acc87a0a9..99c41128e5b8 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -122,22 +122,114 @@ log (char const * fmt, ...) class insn_info { rtx_insn * insn; // the insn + + // usage flags unsigned myuse; // bit set if registers are used in this statement unsigned hard; // bit set if registers can't be renamed unsigned use; // bit set if registers are used in program flow unsigned def; // bit set if registers are defined here + int proepi; // 1 = in prologue, 2 = in epilogue, 0 = other + bool stack; // part of stack frame insns + // stuff to analyze insns + bool label; + bool jump; + bool call; + bool compare; + bool dst_reg; + bool src_reg; + bool dst_mem; + bool src_mem; + bool dst_plus; + bool src_plus; + bool src_const; + + int dst_regno; + int dst_mem_reg; + unsigned dst_mem_addr; + + int src_regno; + int src_mem_regno; + unsigned src_intval; + insn_info & operator = (insn_info const &); public: insn_info (rtx_insn * i = 0, int p = 0) : - insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false) + insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( + false), compare (false), dst_reg (false), src_reg (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus ( + false), src_const (false), dst_regno (-1), dst_mem_reg (-1), dst_mem_addr (0), src_regno (-1), src_mem_regno ( + -1), src_intval (0) + { + } + + inline void + plus_to_move (rtx_insn * newinsn) + { + insn = newinsn; + dst_plus = false; + dst_reg = true; + // usage flags did not change + } + + inline bool + is_dst_reg () const + { + return dst_reg; + } + + inline bool + is_src_reg () const + { + return src_reg; + } + + inline int + get_dst_regno () const + { + return dst_regno; + } + + inline int + get_src_regno () const + { + return src_regno; + } + + inline bool + is_src_plus () const + { + return src_plus; + } + + inline bool + is_src_const () const { + return src_const; } + inline void + mark_jump () + { + jump = true; + } + inline void + mark_call () + { + call = true; + } + inline void + mark_label () + { + label = true; + } + + void + fledder (rtx set); + /* update usage. */ void update (insn_info & o) @@ -470,6 +562,101 @@ insn_info::scan_rtx (rtx x) } } +/* read the set and grab infos */ +void +insn_info::fledder (rtx set) +{ + rtx dst = SET_DEST(set); + rtx src = SET_SRC(set); + + if (dst == cc0_rtx) + { + compare = true; + set = src; + dst = SET_DEST(set); + src = SET_SRC(set); + } + + if (REG_P(dst)) + { + dst_reg = true; + dst_regno = REGNO(dst); + } + else if (MEM_P(dst)) + { + dst_mem = true; + rtx mem = XEXP(dst, 0); + if (REG_P(mem)) + dst_mem_reg = REGNO(mem); + else if (GET_CODE(mem) == CONST_INT) + dst_mem_addr = INTVAL(mem); + else if (GET_CODE(mem) == PLUS) + { + dst_plus = true; + rtx reg = XEXP(mem, 0); + rtx konst = XEXP(mem, 1); + if (REG_P(reg) && GET_CODE(konst) == CONST_INT) + { + dst_mem_reg = REGNO(reg); + dst_mem_addr = INTVAL(konst); + } + } + } + + if (REG_P(src)) + { + src_reg = true; + src_regno = REGNO(src); + } + else if (MEM_P(src)) + { + src_mem = true; + rtx mem = XEXP(src, 0); + if (REG_P(mem)) + src_mem_regno = REGNO(mem); + else if (GET_CODE(mem) == CONST_INT) + src_intval = INTVAL(mem); + else if (GET_CODE(mem) == PLUS) + { + src_plus = true; + rtx reg = XEXP(mem, 0); + rtx konst = XEXP(mem, 1); + if (REG_P(reg) && GET_CODE(konst) == CONST_INT) + { + src_mem_regno = REGNO(reg); + src_const = true; + src_intval = INTVAL(konst); + } + } + } + else if (GET_CODE(src) == CONST_INT) + { + src_const = true; + src_intval = INTVAL(src); + } + else if (GET_CODE(src) == PLUS) + { + src_plus = true; + rtx reg = XEXP(src, 0); + rtx konst = XEXP(src, 1); + if (REG_P(reg)) + { + if (GET_CODE(konst) == CONST_INT) + { + src_regno = REGNO(reg); + src_const = true; + src_intval = INTVAL(konst); + } + else if (REG_P(konst)) + { + src_reg = true; + src_regno = REGNO(konst); + } + } + } + +} + /* create a copy for a reg. Optional specify a new register number. */ static rtx copy_reg (rtx reg, int newregno) @@ -600,6 +787,9 @@ append_reg_usage (FILE * f, rtx_insn * insn) if (ii.is_use (FIRST_PSEUDO_REGISTER)) fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "+cc " : " cc "); + if (f == stderr) + fprintf (f, "\n"); + } /* @@ -635,43 +825,6 @@ dump_insns (char const * name, bool all) } } -/* - * Create a filtered view of insns - keep only those to work with. - */ -static void -update_insns () -{ - rtx_insn *insn, *next; - clear (); - - char inproepilogue = 1; - /* create a vector with relevant insn. */ - for (insn = get_insns (); insn; insn = next) - { - next = NEXT_INSN (insn); - - if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn)) - { - if (JUMP_P(insn)) - jumps.push_back (insn); - - insn2index.insert (std::make_pair (insn, infos.size ())); - infos.push_back (insn_info (insn, inproepilogue)); - - if (JUMP_P(insn)) - inproepilogue = 0; - } - - if (NOTE_P(insn)) - { - if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) - inproepilogue = 0; - else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG) - inproepilogue = 2; - } - } -} - /* This is the important function to track register usage plus hard/live state. * * Start at bottom and work upwards. On all labels trigger all jumps referring to this label. @@ -764,6 +917,62 @@ update_insn_infos (void) } } +/* + * Create a filtered view of insns - keep only those to work with. + */ +static void +update_insns () +{ + rtx_insn *insn, *next; + clear (); + + char inproepilogue = 1; + /* create a vector with relevant insn. */ + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + + if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn)) + { + + insn2index.insert (std::make_pair (insn, infos.size ())); + infos.push_back (insn_info (insn, inproepilogue)); + insn_info & ii = infos[infos.size () - 1]; + + if (JUMP_P(insn)) + { + jumps.push_back (insn); + inproepilogue = 0; + + ii.mark_jump (); + } + else if (LABEL_P(insn)) + { + ii.mark_label (); + } + else if (CALL_P(insn)) + { + ii.mark_call (); + } + else + { + rtx set = single_set (insn); + if (set) + ii.fledder (set); + } + } + + if (NOTE_P(insn)) + { + if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) + inproepilogue = 0; + else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG) + inproepilogue = 2; + } + } + update_insn_infos (); +} + /* convert the lowest set bit into a register number. */ static int bit2regno (unsigned bit) @@ -1714,57 +1923,57 @@ opt_merge_add (void) unsigned change_count = 0; for (unsigned index = 0; index + 2 < infos.size (); ++index) { - rtx_insn * ins1 = infos[index].get_insn (); - rtx_insn * ins2 = infos[index + 1].get_insn (); - rtx_insn * ins3 = infos[index + 2].get_insn (); - if (!NONJUMP_INSN_P(ins1) && !NONJUMP_INSN_P(ins2) && !NONJUMP_INSN_P(ins3)) - continue; + insn_info & ii0 = infos[index]; + insn_info & ii1 = infos[index + 1]; + insn_info & ii2 = infos[index + 2]; - rtx set1 = single_set (ins1); - rtx set2 = single_set (ins2); - rtx set3 = single_set (ins3); - if (!set1 || !set2 || !set3) - continue; + if (!ii2.is_dst_reg ()) + { + index += 2; + continue; + } + + if (!ii1.is_dst_reg ()) + { + ++index; + continue; + } - rtx dst1 = SET_DEST(set1); - rtx dst2 = SET_DEST(set2); - rtx dst3 = SET_DEST(set3); - if (!REG_P(dst1) || !REG_P(dst2) || !REG_P(dst3)) + if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) continue; - CC_STATUS_INIT; - NOTICE_UPDATE_CC(PATTERN (ins2), ins2); - if (cc_status.value1 || cc_status.value2) + if (!ii0.is_src_const () || !ii1.is_src_reg () || !ii2.is_src_const ()) continue; - rtx src1 = SET_SRC(set1); - rtx src2 = SET_SRC(set2); - rtx src3 = SET_SRC(set3); - if (GET_CODE(src1) != PLUS || GET_CODE(src2) != PLUS || GET_CODE(src3) != PLUS) + if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ()) continue; - rtx l1 = XEXP(src1, 0); -// rtx l2 = XEXP(src2, 0); -// rtx l3 = XEXP(src3, 0); + rtx_insn * insn1 = ii1.get_insn (); - rtx r1 = XEXP(src1, 1); - rtx r2 = XEXP(src2, 1); - rtx r3 = XEXP(src3, 1); - if (!CONST_INT_P(r1) || !REG_P(r2) || !CONST_INT_P(r3)) + CC_STATUS_INIT; + NOTICE_UPDATE_CC(PATTERN (insn1), insn1); + if (cc_status.value1 || cc_status.value2) continue; - if (REGNO(dst1) != REGNO(dst2) || REGNO(r2) != REGNO(dst3)) - continue; + log ("%d: merge_add applied\n", index); + + rtx_insn * insn0 = ii0.get_insn (); + rtx set = PATTERN (insn0); - log ("merge_add applied\n"); + // convert lea (-1,a0),a1 into move.l a0,a1 + rtx_insn * newins0 = make_insn_raw (gen_rtx_SET(XEXP(set, 0), XEXP(XEXP(set, 1), 0))); + add_insn_after (newins0, insn0, 0); + SET_INSN_DELETED(insn0); + // update infos accordingly + ii0.plus_to_move (newins0); - rtx_insn * newins1 = make_insn_raw (gen_rtx_SET(dst1, l1)); - add_insn_after (newins1, ins1, 0); - SET_INSN_DELETED(ins1); + rtx_insn * insn2 = ii2.get_insn (); + rtx_insn * newins1 = make_insn_raw (PATTERN (insn1)); + add_insn_after (newins1, insn2, 0); + SET_INSN_DELETED(insn1); +// ii1.swap_adds(newins1, ii2); - rtx_insn * newins2 = make_insn_raw (PATTERN (ins2)); - add_insn_after (newins2, ins3, 0); - SET_INSN_DELETED(ins2); + ++change_count; } return change_count; } @@ -1946,7 +2155,6 @@ opt_shrink_stack_frame (void) ++pos; } /* gather usage stats without prologue/epilogue */ - update_insn_infos (); insn_info ii; for (unsigned i = 0; i < infos.size (); ++i) { @@ -2270,7 +2478,6 @@ namespace { int done = 1; update_insns (); - update_insn_infos (); if (do_opt_strcpy && opt_strcpy ()) done = 0, update_insns (); @@ -2280,22 +2487,20 @@ namespace if (do_propagate_moves && opt_propagate_moves ()) done = 0, update_insns (); - update_insn_infos (); if (do_const_cmp_to_sub && opt_const_cmp_to_sub ()) - done = 0, update_insns (), update_insn_infos (); + done = 0, update_insns (); if (do_merge_add && opt_merge_add ()) - done = 0, update_insns (), update_insn_infos (); + done = 0, update_insns (); if (do_elim_dead_assign && opt_elim_dead_assign ()) - done = 0, update_insns (), update_insn_infos (); + done = 0, update_insns (); if (do_bb_reg_rename) { while (opt_reg_rename ()) { update_insns (); - update_insn_infos (); done = 0; } } @@ -2308,7 +2513,6 @@ namespace { opt_shrink_stack_frame (); update_insns (); - update_insn_infos (); } if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) From c7349bb3c9644ea0ceb0f82b8e739df734db9317 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 28 Apr 2017 13:32:51 +0200 Subject: [PATCH 100/303] @R optimize opt_merge_add - no need to run update_insns afterwards --- gcc/bbb-opts.c | 108 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 99c41128e5b8..9d40a534dc1a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -154,9 +154,6 @@ class insn_info int src_mem_regno; unsigned src_intval; - insn_info & - operator = (insn_info const &); - public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( @@ -166,14 +163,14 @@ class insn_info { } - inline void - plus_to_move (rtx_insn * newinsn) - { - insn = newinsn; - dst_plus = false; - dst_reg = true; - // usage flags did not change - } + int + get_index () const; + + void + plus_to_move (rtx_insn * newinsn); + + void + swap_adds(rtx_insn * newinsn, insn_info & ii); inline bool is_dst_reg () const @@ -715,7 +712,69 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr */ static std::vector infos; static std::vector jumps; -static std::map insn2index; +static std::map insn2index; + +static insn_info * info0; + +static void +update_insn2index () +{ + infos.reserve (infos.size () * 8 / 7 + 2); + insn2index.clear (); + /* needs a separate pass since the insn_infos require fixed addresses for ->get_index() */ + for (unsigned i = 0; i < infos.size (); ++i) + { + insn_info & ii = infos[i]; + insn2index.insert (std::make_pair (ii.get_insn (), &ii)); + } + info0 = &infos[0]; +} + +int +insn_info::get_index () const +{ + insn_info * ii = &infos[0]; + + if (ii == info0) + { + ptrdiff_t diff = ((char const *) this - (char const *) ii); + unsigned pos = diff / sizeof(insn_info); + if (pos < infos.size ()) + return pos; + } + + // realloc happened... + for (unsigned i = 0; i < infos.size (); ++i) + if (infos[i].get_insn () == this->insn) + return i; + + // whoops!? + return 0; +} + +void +insn_info::plus_to_move (rtx_insn * newinsn) +{ + insn = newinsn; + src_plus = false; + src_reg = true; + insn2index.insert(std::make_pair(insn, this)); + // usage flags did not change +} + +void +insn_info::swap_adds(rtx_insn * newinsn, insn_info & ii) +{ + insn = newinsn; + + std::swap(*this, ii); + + insn2index.insert(std::make_pair(insn, this)); + insn2index.insert(std::make_pair(ii.insn, &ii)); + + // usage flags did not change +} + /* * Reset collected data. @@ -759,7 +818,7 @@ append_reg_usage (FILE * f, rtx_insn * insn) if (i == insn2index.end ()) return; - insn_info & ii = infos[i->second]; + insn_info & ii = *i->second; if (f != stderr) fprintf (f, "\n\t\t\t\t\t\t| "); @@ -867,9 +926,9 @@ update_insn_infos (void) { if (JUMP_LABEL(*i) == insn) { - std::map::iterator j = insn2index.find (*i); + auto j = insn2index.find (*i); if (j != insn2index.end ()) - todo.push_back (std::make_pair (j->second, ii)); + todo.push_back (std::make_pair (j->second->get_index (), ii)); } } continue; @@ -935,7 +994,6 @@ update_insns () if (NONJUMP_INSN_P (insn) || LABEL_P(insn) || JUMP_P(insn) || CALL_P(insn)) { - insn2index.insert (std::make_pair (insn, infos.size ())); infos.push_back (insn_info (insn, inproepilogue)); insn_info & ii = infos[infos.size () - 1]; @@ -970,6 +1028,8 @@ update_insns () inproepilogue = 2; } } + + update_insn2index (); update_insn_infos (); } @@ -1088,11 +1148,11 @@ opt_reg_rename (void) { if (JUMP_LABEL(*i) == insn) { - std::map::iterator j = insn2index.find (*i); + auto j = insn2index.find (*i); if (j == insn2index.end ()) continue; - unsigned start = j->second; + unsigned start = j->second->get_index (); if (!infos[start].is_use (rename_regno)) continue; @@ -1131,7 +1191,7 @@ opt_reg_rename (void) /* follow jump and/or next insn. */ if (JUMP_P(insn)) { - std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); + auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); if (j == insn2index.end ()) { /* whoops - label not found. */ @@ -1139,7 +1199,7 @@ opt_reg_rename (void) break; } - unsigned label_index = j->second; + unsigned label_index = j->second->get_index (); if (found.find (label_index) == found.end ()) { /* if the rename_reg is used in the insn before. @@ -1827,9 +1887,9 @@ opt_const_cmp_to_sub (void) if (!JUMP_P(patchme)) continue; - std::map::iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme)); + auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme)); if (j != insn2index.end ()) - todo.push_back (j->second); + todo.push_back (j->second->get_index ()); rtx jmppattern = PATTERN (patchme); @@ -1971,7 +2031,7 @@ opt_merge_add (void) rtx_insn * newins1 = make_insn_raw (PATTERN (insn1)); add_insn_after (newins1, insn2, 0); SET_INSN_DELETED(insn1); -// ii1.swap_adds(newins1, ii2); + ii1.swap_adds(newins1, ii2); ++change_count; } @@ -2491,7 +2551,7 @@ namespace done = 0, update_insns (); if (do_merge_add && opt_merge_add ()) - done = 0, update_insns (); + done = 0; if (do_elim_dead_assign && opt_elim_dead_assign ()) done = 0, update_insns (); From 6bfa56b92ce1a9b99b72ef18b7ba14d71542ef8e Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 28 Apr 2017 17:45:15 +0200 Subject: [PATCH 101/303] @N add opt_immediate --- gcc/bbb-opts.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 163 insertions(+), 11 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9d40a534dc1a..aa841f737cf8 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -170,7 +170,10 @@ class insn_info plus_to_move (rtx_insn * newinsn); void - swap_adds(rtx_insn * newinsn, insn_info & ii); + swap_adds (rtx_insn * newinsn, insn_info & ii); + + void + immediate2base (unsigned regno, unsigned base); inline bool is_dst_reg () const @@ -178,6 +181,48 @@ class insn_info return dst_reg; } + inline bool + is_dst_mem () const + { + return dst_mem; + } + + inline bool + has_dst_memreg () const + { + return dst_mem_reg >= 0; + } + + inline bool + has_dst_addr () const + { + return dst_mem_addr != 0; + } + + inline bool + is_label () const + { + return label; + } + + inline bool + is_jump () const + { + return jump; + } + + inline bool + is_call () const + { + return call; + } + + inline unsigned + get_dst_addr () const + { + return dst_mem_addr; + } + inline bool is_src_reg () const { @@ -447,7 +492,7 @@ class insn_info if (def & hard) return 0; - if (!def || def > 0x1000) + if (!def || (def & ~(1 << FIRST_PSEUDO_REGISTER)) > 0x1000) return 0; unsigned mask = def - 1; @@ -758,24 +803,53 @@ insn_info::plus_to_move (rtx_insn * newinsn) insn = newinsn; src_plus = false; src_reg = true; - insn2index.insert(std::make_pair(insn, this)); + insn2index.insert (std::make_pair (insn, this)); // usage flags did not change } void -insn_info::swap_adds(rtx_insn * newinsn, insn_info & ii) +insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii) { insn = newinsn; - std::swap(*this, ii); + std::swap (*this, ii); - insn2index.insert(std::make_pair(insn, this)); - insn2index.insert(std::make_pair(ii.insn, &ii)); + insn2index.insert (std::make_pair (insn, this)); + insn2index.insert (std::make_pair (ii.insn, &ii)); // usage flags did not change } +void +insn_info::immediate2base (unsigned regno, unsigned base) +{ + rtx set = PATTERN (get_insn ()); + rtx src = SET_SRC(set); + machine_mode mode = GET_MODE(SET_DEST(set)); + + unsigned addr = get_dst_addr (); + unsigned offset = addr - base; + + rtx pattern; + if (base == addr) + pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_raw_REG (SImode, regno)), SET_SRC(set)); + else + pattern = gen_rtx_SET( + gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, gen_raw_REG (SImode, regno), gen_rtx_CONST_INT(SImode, offset))), + SET_SRC(set)); + + SET_INSN_DELETED(insn); + insn = emit_insn_after (pattern, insn); + + mark_use (regno); + + dst_mem_reg = regno; + dst_mem = true; + dst_mem_addr = offset; + dst_plus = offset != 0; + insn2index.insert (std::make_pair (insn, this)); +} /* * Reset collected data. */ @@ -1987,19 +2061,19 @@ opt_merge_add (void) insn_info & ii1 = infos[index + 1]; insn_info & ii2 = infos[index + 2]; - if (!ii2.is_dst_reg ()) + if (!ii2.is_dst_reg () || ii2.is_dst_mem ()) { index += 2; continue; } - if (!ii1.is_dst_reg ()) + if (!ii1.is_dst_reg () || ii1.is_dst_mem ()) { ++index; continue; } - if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) + if (ii0.is_dst_mem () || !ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) continue; if (!ii0.is_src_const () || !ii1.is_src_reg () || !ii2.is_src_const ()) @@ -2031,7 +2105,7 @@ opt_merge_add (void) rtx_insn * newins1 = make_insn_raw (PATTERN (insn1)); add_insn_after (newins1, insn2, 0); SET_INSN_DELETED(insn1); - ii1.swap_adds(newins1, ii2); + ii1.swap_adds (newins1, ii2); ++change_count; } @@ -2464,6 +2538,80 @@ opt_shrink_stack_frame (void) return 0; } +static unsigned +opt_immediate (void) +{ + unsigned change_count = 0; + + for (unsigned i = 0; i < infos.size (); ++i) + { + insn_info & ii = infos[i]; + if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg()) + continue; + + unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00; + if (!freemask) + continue; + + std::vector found; + found.push_back (i); + unsigned base = ii.get_dst_addr (); + unsigned j = i + 1; + for (; j < infos.size (); ++j) + { + insn_info & jj = infos[j]; + if (jj.is_label () || jj.is_jump () || jj.is_call ()) + break; + + freemask &= ~(jj.get_use () | jj.get_def ()); + if (!freemask) + break; + + if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg()) + { + unsigned addr = jj.get_dst_addr (); + if (addr < base) + base = addr; + if (addr - base > 0x7ffc) + continue; + + found.push_back (j); + } + } + + if (freemask && found.size () > 2) + { + unsigned regno = bit2regno (freemask); + log ("modifying %d immediate using %s\n", found.size (), reg_names[regno]); + + for (auto k = found.begin (); k != found.end (); ++k) + { + insn_info & kk = infos[*k]; + kk.immediate2base (regno, base); + } + + // load base into reg + rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); + rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); + insn_info nn (insn); + nn.scan(); + nn.fledder (lea); + nn.mark_def (regno); + infos.insert (infos.begin () + i, nn); + while (i++ < j) + infos[i].mark_use(regno); + ++j; + } + + i = j; + } + + if (change_count) + update_insn2index (); + + return change_count; +} + namespace { @@ -2533,6 +2681,7 @@ namespace bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+'); bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); + bool do_immediate = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); for (;;) { @@ -2556,6 +2705,9 @@ namespace if (do_elim_dead_assign && opt_elim_dead_assign ()) done = 0, update_insns (); + if (do_immediate && opt_immediate ()) + done = 0, update_insns (); + if (do_bb_reg_rename) { while (opt_reg_rename ()) From d851a82657b37cc2fd5f8077fd97c9ea8bef0bfc Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 28 Apr 2017 18:21:19 +0200 Subject: [PATCH 102/303] @B fix opt_merge_add --- gcc/bbb-opts.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index aa841f737cf8..face11f85f8a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -187,6 +187,12 @@ class insn_info return dst_mem; } + inline bool + is_src_mem () const + { + return src_mem; + } + inline bool has_dst_memreg () const { @@ -2073,10 +2079,10 @@ opt_merge_add (void) continue; } - if (ii0.is_dst_mem () || !ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) + if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) continue; - if (!ii0.is_src_const () || !ii1.is_src_reg () || !ii2.is_src_const ()) + if (ii0.is_src_mem () || !ii0.is_src_const () || !ii1.is_src_reg () || ii2.is_src_mem () || !ii2.is_src_const ()) continue; if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ()) From 25996bade9f5e8d41f81fac1d07cb82cebe5832c Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 28 Apr 2017 21:55:59 +0200 Subject: [PATCH 103/303] @B fix opt_immediate: update reg usage --- gcc/bbb-opts.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index face11f85f8a..5683ac21640b 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -358,6 +358,13 @@ class insn_info { return use; } + + inline void + set_use(unsigned u) + { + use = u; + } + inline unsigned get_def () const { @@ -1288,7 +1295,7 @@ opt_reg_rename (void) insn_info & bb = infos[label_index + 1]; if (bb.is_use (rename_regno)) { - unsigned start = find_start (found, label_index - 1, rename_regno); + unsigned start = find_start (found, label_index, rename_regno); todo.push_back (start); } todo.push_back (label_index + 1); @@ -2600,6 +2607,7 @@ opt_immediate (void) rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); insn_info nn (insn); + nn.set_use(ii.get_use()); nn.scan(); nn.fledder (lea); nn.mark_def (regno); From 3fdf716d76ad01cdef87f14ebceb8832ca9b32a7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 28 Apr 2017 23:07:13 +0200 Subject: [PATCH 104/303] @B fix opt_immediate: update reg usage --- gcc/bbb-opts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 5683ac21640b..99c49db4238d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2615,6 +2615,7 @@ opt_immediate (void) while (i++ < j) infos[i].mark_use(regno); ++j; + ++change_count; } i = j; From b68846bfd5192be42bf080d09e429227aebdb7d3 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 30 Apr 2017 18:27:54 +0200 Subject: [PATCH 105/303] @I cleanup, remove unnecessary changes --- .cproject | 6 +++++- gcc/DATESTAMP | 2 +- gcc/cfgbuild.c | 1 - gcc/config/m68k/amigaos.c | 10 ---------- gcc/config/m68k/amigaos.h | 4 ---- gcc/doc/tm.texi | 4 ---- gcc/doc/tm.texi.in | 2 -- gcc/final.c | 7 +------ gcc/regrename.c | 5 ++--- gcc/target.def | 19 ------------------- gcc/targhooks.c | 7 ------- gcc/targhooks.h | 1 - gcc/toplev.c | 2 +- 13 files changed, 10 insertions(+), 60 deletions(-) diff --git a/.cproject b/.cproject index 62b1c0f38dcb..b3cddaefb27b 100755 --- .cproject +++ .cproject @@ -42,6 +42,7 @@ @@ -56,12 +57,13 @@ - @@ -115,6 +118,7 @@ diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index efbcba2793ea..59aff9a1ff47 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170426 +20170430 diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 1f488dc54544..c1ec46ad8d7f 100644 --- gcc/cfgbuild.c +++ gcc/cfgbuild.c @@ -55,7 +55,6 @@ inside_basic_block_p (const rtx_insn *insn) case DEBUG_INSN: return true; - case DEBUG_IMPLICIT_PTR: case JUMP_TABLE_DATA: case BARRIER: case NOTE: diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 27831df2d543..419d59dc3871 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -839,13 +839,3 @@ read_only_operand (rtx operand) return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P(operand); return 1; } - -reg_class_t -amiga_preferred_rename_class2 (reg_class_t rclass ATTRIBUTE_UNUSED, int regno) -{ - if (regno == 0) - return D0_REGS; - if (regno == 8) - return A0_REGS; - return regno_reg_class[regno]; -} diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 49dd90d745c3..e2a2b4cc11f6 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -486,7 +486,3 @@ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool); && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ ) -#undef TARGET_PREFERRED_RENAME_CLASS2 -#define TARGET_PREFERRED_RENAME_CLASS2 amiga_preferred_rename_class2 -reg_class_t -amiga_preferred_rename_class2(reg_class_t, int); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 6604514427fa..745910f9a331 100644 --- gcc/doc/tm.texi +++ gcc/doc/tm.texi @@ -2489,10 +2489,6 @@ only if neither labeling works. A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class}, code size can be reduced. @end deftypefn -@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RENAME_CLASS2 (reg_class_t @var{rclass}, int @var{regno}) -A target hook that places additional preference on the register class to use when it is necessary to rename a register in class @var{rclass} to another class, or perhaps @var{NO_REGS}, if no preferred register class is found or hook @code{preferred_rename_class2} is not implemented. Sometimes returning a more restrictive class makes better code. For example, on ARM, thumb-2 instructions using @code{LO_REGS} may be smaller than instructions using @code{GENERIC_REGS}. By returning @code{LO_REGS} from @code{preferred_rename_class2}, code size can be reduced. -@end deftypefn - @deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass}) A target hook that places additional restrictions on the register class to use when it is necessary to copy value @var{x} into a register in class diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index e4da2a94249b..f31c763991c5 100644 --- gcc/doc/tm.texi.in +++ gcc/doc/tm.texi.in @@ -2281,8 +2281,6 @@ only if neither labeling works. @hook TARGET_PREFERRED_RENAME_CLASS -@hook TARGET_PREFERRED_RENAME_CLASS2 - @hook TARGET_PREFERRED_RELOAD_CLASS @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class}) diff --git a/gcc/final.c b/gcc/final.c index 31f9b4815d75..55cf509611f7 100644 --- gcc/final.c +++ gcc/final.c @@ -2165,7 +2165,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, /* Ignore deleted insns. These can occur when we split insns (due to a template of "#") while not optimizing. */ - if (insn->deleted () || GET_CODE(insn) == VALUE || GET_CODE(insn) == CONST_FIXED || GET_CODE(insn) == DEBUG_IMPLICIT_PTR) + if (insn->deleted ()) return NEXT_INSN (insn); switch (GET_CODE (insn)) @@ -4430,17 +4430,12 @@ leaf_renumber_regs_insn (rtx in_rtx) } #endif - -extern void dump_insns(char const *); - /* Turn the RTL into assembly. */ static unsigned int rest_of_handle_final (void) { const char *fnname = get_fnname_from_decl (current_function_decl); -// dump_insns("final"); - assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); final (get_insns (), asm_out_file, optimize); diff --git a/gcc/regrename.c b/gcc/regrename.c index 1ed6557ee713..b3818a80846d 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -406,9 +406,8 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, /* In the first pass, we force the renaming of registers that don't belong to PREFERRED_CLASS to registers that do, even - though the latters were used not very long ago. - Also use a register if no best_new_reg was found till now */ - if (((pass == 0 || !has_preferred_class) + though the latters were used not very long ago. */ + if ((pass == 0 && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], best_new_reg)) || tick[best_new_reg] > tick[new_reg]) diff --git a/gcc/target.def b/gcc/target.def index d0208812d83b..20f2b32da1e9 100644 --- gcc/target.def +++ gcc/target.def @@ -5170,25 +5170,6 @@ DEFHOOK reg_class_t, (reg_class_t rclass), default_preferred_rename_class) -/*A target hook that places additional preference on the register - class - */ -DEFHOOK -(preferred_rename_class2, - "A target hook that places additional preference on the register\ - class to use when it is necessary to rename a register in class\ - @var{rclass} to another class, or perhaps @var{NO_REGS}, if no\ - preferred register class is found or hook @code{preferred_rename_class2}\ - is not implemented.\ - Sometimes returning a more restrictive class makes better code. For\ - example, on ARM, thumb-2 instructions using @code{LO_REGS} may be\ - smaller than instructions using @code{GENERIC_REGS}. By returning\ - @code{LO_REGS} from @code{preferred_rename_class2}, code size can\ - be reduced.", - reg_class_t, (reg_class_t rclass, int regno), - default_preferred_rename_class2) - - /* This target hook allows the backend to avoid unsafe substitution during register allocation. */ DEFHOOK diff --git a/gcc/targhooks.c b/gcc/targhooks.c index e106af7b261d..a34227705d2b 100644 --- gcc/targhooks.c +++ gcc/targhooks.c @@ -1542,13 +1542,6 @@ default_preferred_rename_class (reg_class_t rclass ATTRIBUTE_UNUSED) return NO_REGS; } -/* The default implementation of TARGET_PREFERRED_RENAME_CLASS2. */ -reg_class_t -default_preferred_rename_class2 (reg_class_t rclass, int regno ATTRIBUTE_UNUSED) -{ - return targetm.preferred_rename_class(rclass); -} - /* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P. */ bool diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 0a21ef982a65..7687c39b53b5 100644 --- gcc/targhooks.h +++ gcc/targhooks.h @@ -204,7 +204,6 @@ extern bool default_profile_before_prologue (void); extern reg_class_t default_preferred_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_rename_class (reg_class_t rclass); -extern reg_class_t default_preferred_rename_class2 (reg_class_t rclass, int regno); extern bool default_class_likely_spilled_p (reg_class_t); extern unsigned char default_class_max_nregs (reg_class_t, machine_mode); diff --git a/gcc/toplev.c b/gcc/toplev.c index 83800763f30d..59604e56195b 100644 --- gcc/toplev.c +++ gcc/toplev.c @@ -1324,7 +1324,7 @@ process_options (void) flag_web = flag_unroll_loops || flag_peel_loops; if (flag_rename_registers == AUTODETECT_VALUE) - flag_rename_registers = flag_unroll_loops || flag_peel_loops || optimize >= 2; + flag_rename_registers = flag_unroll_loops || flag_peel_loops; if (flag_non_call_exceptions) flag_asynchronous_unwind_tables = 1; From beb1cfb6a364fbe542b38cc4a4206219b465a671 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 2 May 2017 22:42:17 +0200 Subject: [PATCH 106/303] @B fix stack frame shrink/removal with frame pointer, @I some internal changes --- gcc/bbb-opts.c | 236 +++++++++++++++++++++++++++++++++++--------------------- gcc/regrename.c | 5 +- 2 files changed, 153 insertions(+), 88 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 99c49db4238d..6a27fcf72544 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -75,7 +75,12 @@ bool be_very_verbose; bool be_verbose; #ifdef __ECLIPSE__ -extern char * string_bbb_opts; +//extern char * string_bbb_opts; +#define FIRST_PSEUDO_REGISTER 25 +#define FRAME_POINTER_REGNUM 13 +#define STACK_POINTER_REGNUM 15 +#define NOTICE_UPDATE_CC(a,b) +#define Pmode SImode #endif extern struct lang_hooks lang_hooks; @@ -138,28 +143,25 @@ class insn_info bool jump; bool call; bool compare; - bool dst_reg; - bool src_reg; bool dst_mem; bool src_mem; bool dst_plus; bool src_plus; bool src_const; - int dst_regno; - int dst_mem_reg; + rtx dst_reg; + rtx dst_mem_reg; + rtx src_reg; + rtx src_mem_reg; unsigned dst_mem_addr; - int src_regno; - int src_mem_regno; unsigned src_intval; public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( - false), compare (false), dst_reg (false), src_reg (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus ( - false), src_const (false), dst_regno (-1), dst_mem_reg (-1), dst_mem_addr (0), src_regno (-1), src_mem_regno ( - -1), src_intval (0) + false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const ( + false), dst_reg (0), dst_mem_reg (0), src_reg (0), src_mem_reg (0), dst_mem_addr (0), src_intval (0) { } @@ -173,7 +175,7 @@ class insn_info swap_adds (rtx_insn * newinsn, insn_info & ii); void - immediate2base (unsigned regno, unsigned base); + absolute2base (unsigned regno, unsigned base); inline bool is_dst_reg () const @@ -196,13 +198,13 @@ class insn_info inline bool has_dst_memreg () const { - return dst_mem_reg >= 0; + return dst_mem_reg; } inline bool has_dst_addr () const { - return dst_mem_addr != 0; + return dst_mem_addr; } inline bool @@ -232,25 +234,55 @@ class insn_info inline bool is_src_reg () const { - return src_reg; + return src_reg && !src_plus; + } + + inline bool + is_src_plus () const + { + return src_reg && src_plus; + } + + inline bool + is_src_mem_plus () const + { + return src_mem && src_plus; } inline int get_dst_regno () const { - return dst_regno; + return dst_reg ? REGNO(dst_reg) : -1; } inline int get_src_regno () const { - return src_regno; + return src_reg ? REGNO(src_reg) : -1; } - inline bool - is_src_plus () const + inline rtx + get_src_reg () const + { + return src_reg; + } + + inline rtx + get_dst_reg () const + { + return dst_reg; + } + + inline int + get_src_mem_regno () const + { + return src_mem_reg ? REGNO(src_mem_reg) : -1; + } + + inline int + get_src_intval () const { - return src_plus; + return src_intval; } inline bool @@ -360,7 +392,7 @@ class insn_info } inline void - set_use(unsigned u) + set_use (unsigned u) { use = u; } @@ -431,6 +463,13 @@ class insn_info return *this; } + inline insn_info & + or_use (insn_info const & o) + { + use |= o.myuse | o.def | o.hard; + return *this; + } + inline insn_info & drop_def () { @@ -524,6 +563,10 @@ class insn_info { return def & ~hard & ~use & 0x7fff; } + + void + set_insn (rtx_insn * newinsn); + }; void @@ -634,15 +677,14 @@ insn_info::fledder (rtx set) if (REG_P(dst)) { - dst_reg = true; - dst_regno = REGNO(dst); + dst_reg = dst; } else if (MEM_P(dst)) { dst_mem = true; rtx mem = XEXP(dst, 0); if (REG_P(mem)) - dst_mem_reg = REGNO(mem); + dst_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) dst_mem_addr = INTVAL(mem); else if (GET_CODE(mem) == PLUS) @@ -652,7 +694,7 @@ insn_info::fledder (rtx set) rtx konst = XEXP(mem, 1); if (REG_P(reg) && GET_CODE(konst) == CONST_INT) { - dst_mem_reg = REGNO(reg); + dst_mem_reg = reg; dst_mem_addr = INTVAL(konst); } } @@ -660,15 +702,14 @@ insn_info::fledder (rtx set) if (REG_P(src)) { - src_reg = true; - src_regno = REGNO(src); + src_reg = src; } else if (MEM_P(src)) { src_mem = true; rtx mem = XEXP(src, 0); if (REG_P(mem)) - src_mem_regno = REGNO(mem); + src_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) src_intval = INTVAL(mem); else if (GET_CODE(mem) == PLUS) @@ -678,7 +719,7 @@ insn_info::fledder (rtx set) rtx konst = XEXP(mem, 1); if (REG_P(reg) && GET_CODE(konst) == CONST_INT) { - src_mem_regno = REGNO(reg); + src_mem_reg = reg; src_const = true; src_intval = INTVAL(konst); } @@ -698,14 +739,13 @@ insn_info::fledder (rtx set) { if (GET_CODE(konst) == CONST_INT) { - src_regno = REGNO(reg); + src_reg = reg; src_const = true; src_intval = INTVAL(konst); } else if (REG_P(konst)) { - src_reg = true; - src_regno = REGNO(konst); + src_reg = konst; } } } @@ -815,7 +855,7 @@ insn_info::plus_to_move (rtx_insn * newinsn) { insn = newinsn; src_plus = false; - src_reg = true; + src_reg = XEXP(PATTERN (newinsn), 1); insn2index.insert (std::make_pair (insn, this)); // usage flags did not change } @@ -834,7 +874,14 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii) } void -insn_info::immediate2base (unsigned regno, unsigned base) +insn_info::set_insn (rtx_insn * newinsn) +{ + insn = newinsn; + fledder (PATTERN (insn)); +} + +void +insn_info::absolute2base (unsigned regno, unsigned base) { rtx set = PATTERN (get_insn ()); rtx src = SET_SRC(set); @@ -844,19 +891,18 @@ insn_info::immediate2base (unsigned regno, unsigned base) unsigned offset = addr - base; rtx pattern; + rtx reg = gen_raw_REG (SImode, regno); if (base == addr) - pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_raw_REG (SImode, regno)), SET_SRC(set)); + pattern = gen_rtx_SET(gen_rtx_MEM (mode, reg), src); else - pattern = gen_rtx_SET( - gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, gen_raw_REG (SImode, regno), gen_rtx_CONST_INT(SImode, offset))), - SET_SRC(set)); + pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT(SImode, offset))), src); SET_INSN_DELETED(insn); insn = emit_insn_after (pattern, insn); mark_use (regno); - dst_mem_reg = regno; + dst_mem_reg = reg; dst_mem = true; dst_mem_addr = offset; dst_plus = offset != 0; @@ -908,7 +954,7 @@ append_reg_usage (FILE * f, rtx_insn * insn) insn_info & ii = *i->second; if (f != stderr) - fprintf (f, "\n\t\t\t\t\t\t| "); + fprintf (f, "\n\t\t\t\t\t\t|%c ", ii.is_stack () ? 's' : ' '); for (int j = 0; j < 8; ++j) if (ii.is_use (j) || ii.is_def (j)) @@ -1046,7 +1092,7 @@ update_insn_infos (void) if (!use.is_def (FIRST_PSEUDO_REGISTER)) { CC_STATUS_INIT; - NOTICE_UPDATE_CC(PATTERN (insn), insn); + NOTICE_UPDATE_CC (PATTERN (insn), insn); if (cc_status.value1 || cc_status.value2) use.mark_def (FIRST_PSEUDO_REGISTER); } @@ -1706,7 +1752,7 @@ opt_strcpy () if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead (REGNO(dst), index)) { /* now check via NOTICE_UPDATE_CC*/ - NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x); + NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x); if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2)) { int num_clobbers_to_add = 0; @@ -2074,13 +2120,13 @@ opt_merge_add (void) insn_info & ii1 = infos[index + 1]; insn_info & ii2 = infos[index + 2]; - if (!ii2.is_dst_reg () || ii2.is_dst_mem ()) + if (!ii2.is_dst_reg ()) { index += 2; continue; } - if (!ii1.is_dst_reg () || ii1.is_dst_mem ()) + if (!ii1.is_dst_reg ()) { ++index; continue; @@ -2089,7 +2135,7 @@ opt_merge_add (void) if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) continue; - if (ii0.is_src_mem () || !ii0.is_src_const () || !ii1.is_src_reg () || ii2.is_src_mem () || !ii2.is_src_const ()) + if (!ii0.is_src_const () || !ii2.is_src_const () || ii0.get_src_intval () != ii2.get_src_intval ()) continue; if (ii0.get_dst_regno () != ii1.get_dst_regno () || ii1.get_src_regno () != ii2.get_dst_regno ()) @@ -2098,7 +2144,7 @@ opt_merge_add (void) rtx_insn * insn1 = ii1.get_insn (); CC_STATUS_INIT; - NOTICE_UPDATE_CC(PATTERN (insn1), insn1); + NOTICE_UPDATE_CC (PATTERN (insn1), insn1); if (cc_status.value1 || cc_status.value2) continue; @@ -2182,6 +2228,7 @@ opt_shrink_stack_frame (void) { rtx set = XVECEXP(pattern, 0, 0); rtx dst = SET_DEST(set); + ii.mark_stack (); /* ignore link a5 */ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) { @@ -2190,11 +2237,6 @@ opt_shrink_stack_frame (void) set = XVECEXP(pattern, 0, 2); a5offset = INTVAL(XEXP(SET_SRC(set), 1)); } - else - { - /* use movem */ - ii.mark_stack (); - } ++pos; continue; } @@ -2269,6 +2311,7 @@ opt_shrink_stack_frame (void) { rtx set = XVECEXP(pattern, 0, 0); rtx dst = SET_DEST(set); + ii.mark_stack (); /* unlink is last. */ if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) { @@ -2276,8 +2319,6 @@ opt_shrink_stack_frame (void) break; } - /* movem. */ - ii.mark_stack (); } else if (GET_CODE(pattern) == SET) { @@ -2295,6 +2336,12 @@ opt_shrink_stack_frame (void) if (REG_P(reg) && REGNO(reg) == STACK_POINTER_REGNUM) ii.mark_stack (); } + else if (GET_CODE(postinc) == PLUS) + { + rtx a5 = XEXP(postinc, 0); + if (REG_P(a5) && REGNO(a5) == FRAME_POINTER_REGNUM) + ii.mark_stack (); + } } } } @@ -2306,16 +2353,17 @@ opt_shrink_stack_frame (void) for (unsigned i = 0; i < infos.size (); ++i) { insn_info & jj = infos[i]; - if (jj.is_stack ()) + if (jj.in_proepi ()) continue; - ii.merge (jj); + ii.or_use (jj); } - unsigned freemask = ~ii.get_use (); + unsigned freemask = ~ii.get_use () & 0x7fff; rtx a7 = gen_raw_REG (SImode, STACK_POINTER_REGNUM); rtx a5 = gen_raw_REG (SImode, FRAME_POINTER_REGNUM); + unsigned changed = 0; unsigned adjust = 0; /* now all push/pop insns are in temp. */ for (unsigned i = 0; i < infos.size (); ++i) @@ -2339,8 +2387,8 @@ opt_shrink_stack_frame (void) clobbers.push_back (set); continue; } - rtx src = SET_SRC(set); rtx dst = SET_DEST(set); + rtx src = SET_SRC(set); rtx reg; if (MEM_P(src)) reg = dst; @@ -2349,6 +2397,13 @@ opt_shrink_stack_frame (void) else continue; + if (REGNO(reg) == FRAME_POINTER_REGNUM) + { + // mark as "do not touch" + clobbers.push_back (reg); + break; + } + if (i < prologueend) paramstart += 4; unsigned regbit = 1 << REGNO(reg); @@ -2378,6 +2433,7 @@ opt_shrink_stack_frame (void) log ("shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); if (regs.size () <= 2) { + changed = 1; for (unsigned k = 0; k < regs.size (); ++k) { rtx reg = regs[k]; @@ -2453,6 +2509,7 @@ opt_shrink_stack_frame (void) emit_insn_after (parallel, insn); } SET_INSN_DELETED(insn); + changed = 1; } } else @@ -2470,6 +2527,7 @@ opt_shrink_stack_frame (void) adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; log ("remove push for %s\n", reg_names[REGNO(src)]); SET_INSN_DELETED(insn); + ++changed; } } else @@ -2481,6 +2539,7 @@ opt_shrink_stack_frame (void) { log ("remove pop for %s\n", reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); + ++changed; } } } @@ -2524,42 +2583,47 @@ opt_shrink_stack_frame (void) if (usea5 && a5offset == -4) { - for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) - { - insn_info & ii = infos[*i]; - ii.mark_stack (); - } - for (unsigned i = 0; i < infos.size (); ++i) - { - insn_info ii; - insn_info & jj = infos[i]; - if (jj.is_stack ()) - continue; - - ii.merge (jj); - } - unsigned freemask = ~ii.get_use (); - if (freemask & (1 << FRAME_POINTER_REGNUM)) { log ("dropping unused frame pointer\n"); for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) SET_INSN_DELETED(infos[*i].get_insn ()); + + /* convert parameter access via a5 into a7. */ + for (unsigned i = 0; i < infos.size (); ++i) + { + insn_info & ii = infos[i]; + + if (ii.is_dst_reg () && ii.get_src_mem_regno () == FRAME_POINTER_REGNUM) + { + rtx x = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - 4); + rtx p = gen_rtx_PLUS(SImode, a7, x); + rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1), gen_rtx_MEM (SImode, p)); + set_insn_deleted (ii.get_insn ()); + rtx_insn * newinsn = emit_insn_after (pattern, ii.get_insn ()); + ii.plus_to_move (newinsn); + } + } + + ++changed; } } - return 0; + return changed; } +/* + * Convert a series of move into absolute address into register based moves. + */ static unsigned -opt_immediate (void) +opt_absolute (void) { unsigned change_count = 0; for (unsigned i = 0; i < infos.size (); ++i) { insn_info & ii = infos[i]; - if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg()) + if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg ()) continue; unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00; @@ -2580,7 +2644,7 @@ opt_immediate (void) if (!freemask) break; - if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg()) + if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg ()) { unsigned addr = jj.get_dst_addr (); if (addr < base) @@ -2600,20 +2664,20 @@ opt_immediate (void) for (auto k = found.begin (); k != found.end (); ++k) { insn_info & kk = infos[*k]; - kk.immediate2base (regno, base); + kk.absolute2base (regno, base); } // load base into reg rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); insn_info nn (insn); - nn.set_use(ii.get_use()); - nn.scan(); + nn.set_use (ii.get_use ()); + nn.scan (); nn.fledder (lea); nn.mark_def (regno); infos.insert (infos.begin () + i, nn); while (i++ < j) - infos[i].mark_use(regno); + infos[i].mark_use (regno); ++j; ++change_count; } @@ -2686,7 +2750,7 @@ namespace pass_bbb_optimizations::execute_bbb_optimizations (void) { be_very_verbose = strchr (string_bbb_opts, 'V'); - be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v'); + be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1; bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); @@ -2696,7 +2760,7 @@ namespace bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+'); bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); - bool do_immediate = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); + bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); for (;;) { @@ -2720,8 +2784,8 @@ namespace if (do_elim_dead_assign && opt_elim_dead_assign ()) done = 0, update_insns (); - if (do_immediate && opt_immediate ()) - done = 0, update_insns (); + if (do_absolute && opt_absolute ()) + done = 0; if (do_bb_reg_rename) { @@ -2738,8 +2802,8 @@ namespace if (do_shrink_stack_frame) { - opt_shrink_stack_frame (); - update_insns (); + if (opt_shrink_stack_frame ()) + update_insns (); } if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) diff --git a/gcc/regrename.c b/gcc/regrename.c index b3818a80846d..1ed6557ee713 100755 --- gcc/regrename.c +++ gcc/regrename.c @@ -406,8 +406,9 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class, /* In the first pass, we force the renaming of registers that don't belong to PREFERRED_CLASS to registers that do, even - though the latters were used not very long ago. */ - if ((pass == 0 + though the latters were used not very long ago. + Also use a register if no best_new_reg was found till now */ + if (((pass == 0 || !has_preferred_class) && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class], best_new_reg)) || tick[best_new_reg] > tick[new_reg]) From f3a773accb47542fef665cf044dad13366139ab5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 3 May 2017 09:33:02 +0200 Subject: [PATCH 107/303] @B fix shrink stack frame for 8 byte parameters --- gcc/bbb-opts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 6a27fcf72544..e8000a01ce49 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2598,7 +2598,8 @@ opt_shrink_stack_frame (void) { rtx x = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - 4); rtx p = gen_rtx_PLUS(SImode, a7, x); - rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1), gen_rtx_MEM (SImode, p)); + rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1), + gen_rtx_MEM (GET_MODE(ii.get_dst_reg ()), p)); set_insn_deleted (ii.get_insn ()); rtx_insn * newinsn = emit_insn_after (pattern, ii.get_insn ()); ii.plus_to_move (newinsn); From c391e554b0a0d6fad5b78ed5ace23eab60cbbe3d Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 3 May 2017 12:57:04 +0200 Subject: [PATCH 108/303] @N opt_absolute also optimizes symbol refs --- gcc/bbb-opts.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index e8000a01ce49..d54da597123b 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -81,6 +81,7 @@ bool be_verbose; #define STACK_POINTER_REGNUM 15 #define NOTICE_UPDATE_CC(a,b) #define Pmode SImode +#define PIC_REG 12 #endif extern struct lang_hooks lang_hooks; @@ -151,8 +152,10 @@ class insn_info rtx dst_reg; rtx dst_mem_reg; + rtx dst_symbol; rtx src_reg; rtx src_mem_reg; + rtx src_symbol; unsigned dst_mem_addr; unsigned src_intval; @@ -161,7 +164,8 @@ class insn_info insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const ( - false), dst_reg (0), dst_mem_reg (0), src_reg (0), src_mem_reg (0), dst_mem_addr (0), src_intval (0) + false), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr ( + 0), src_intval (0) { } @@ -201,6 +205,12 @@ class insn_info return dst_mem_reg; } + inline rtx + get_dst_symbol () const + { + return dst_symbol; + } + inline bool has_dst_addr () const { @@ -687,6 +697,8 @@ insn_info::fledder (rtx set) dst_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) dst_mem_addr = INTVAL(mem); + else if (GET_CODE(mem) == SYMBOL_REF) + dst_symbol = mem; else if (GET_CODE(mem) == PLUS) { dst_plus = true; @@ -698,6 +710,20 @@ insn_info::fledder (rtx set) dst_mem_addr = INTVAL(konst); } } + else if (GET_CODE(mem) == CONST) + { + mem = XEXP(mem, 0); + if (GET_CODE(mem) == PLUS) + { + rtx sym = XEXP(mem, 0); + if (GET_CODE(sym) == SYMBOL_REF) + { + dst_plus = true; + dst_symbol = sym; + dst_mem_addr = INTVAL(XEXP(mem, 1)); + } + } + } } if (REG_P(src)) @@ -712,6 +738,8 @@ insn_info::fledder (rtx set) src_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) src_intval = INTVAL(mem); + else if (GET_CODE(mem) == SYMBOL_REF) + src_symbol = mem; else if (GET_CODE(mem) == PLUS) { src_plus = true; @@ -724,6 +752,20 @@ insn_info::fledder (rtx set) src_intval = INTVAL(konst); } } + else if (GET_CODE(mem) == CONST) + { + mem = XEXP(mem, 0); + if (GET_CODE(mem) == PLUS) + { + rtx sym = XEXP(mem, 0); + if (GET_CODE(sym) == SYMBOL_REF) + { + src_plus = true; + src_symbol = sym; + src_intval = INTVAL(XEXP(mem, 1)); + } + } + } } else if (GET_CODE(src) == CONST_INT) { @@ -749,7 +791,6 @@ insn_info::fledder (rtx set) } } } - } /* create a copy for a reg. Optional specify a new register number. */ @@ -813,6 +854,7 @@ static std::vector jumps; static std::map insn2index; static insn_info * info0; +static unsigned usable_regs; static void update_insn2index () @@ -1107,6 +1149,27 @@ update_insn_infos (void) } ++pass; } + + /* fill the mask of general used regs. */ + insn_info zz; + for (int i = 0; i < infos.size (); ++i) + { + insn_info & ii = infos[i]; + if (ii.in_proepi () != 1) + break; + + zz.or_use (ii); + } + + /* always allow a0/a1, d0/d1. */ + usable_regs = zz.get_use () | 0x303; + if (flag_pic) + usable_regs &= ~(1 << PIC_REG); + + if (infos.size () && infos[0].is_use (FRAME_POINTER_REGNUM)) + usable_regs &= ~(1 << FRAME_POINTER_REGNUM); + + usable_regs &= ~(1 << STACK_POINTER_REGNUM); } /* @@ -2627,10 +2690,12 @@ opt_absolute (void) if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg ()) continue; - unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00; + unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs; if (!freemask) continue; + rtx with_symbol = ii.get_dst_symbol (); + std::vector found; found.push_back (i); unsigned base = ii.get_dst_addr (); @@ -2645,22 +2710,35 @@ opt_absolute (void) if (!freemask) break; - if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg ()) + if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol) { unsigned addr = jj.get_dst_addr (); if (addr < base) base = addr; - if (addr - base > 0x7ffc) - continue; found.push_back (j); } } + if (freemask && found.size () > 2) + { + /* check again. */ + for (auto k = found.begin (); k != found.end ();) + { + insn_info & kk = infos[*k]; + if (kk.get_dst_addr () - base > 0x7ffc) + found.erase (k); + else + ++k; + } + } if (freemask && found.size () > 2) { unsigned regno = bit2regno (freemask); - log ("modifying %d immediate using %s\n", found.size (), reg_names[regno]); + if (with_symbol) + log ("modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]); + else + log ("modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]); for (auto k = found.begin (); k != found.end (); ++k) { @@ -2669,7 +2747,19 @@ opt_absolute (void) } // load base into reg - rtx lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); + rtx lea; + + if (with_symbol) + { + if (base) + lea = gen_rtx_SET( + gen_raw_REG (SImode, regno), + gen_rtx_CONST(SImode, gen_rtx_PLUS(SImode, with_symbol, gen_rtx_CONST_INT (SImode, base)))); + else + lea = gen_rtx_SET(gen_raw_REG (SImode, regno), with_symbol); + } + else + lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); insn_info nn (insn); nn.set_use (ii.get_use ()); From 09c30ec6c5e0bd07fa3d300c2d45cec75f67c783 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 4 May 2017 11:42:43 +0200 Subject: [PATCH 109/303] @B fix dropping stack frame - now only dropped if really unused --- gcc/bbb-opts.c | 246 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 197 insertions(+), 49 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index d54da597123b..a4bb1e0a97a3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -150,6 +150,8 @@ class insn_info bool src_plus; bool src_const; + machine_mode mode; + rtx dst_reg; rtx dst_mem_reg; rtx dst_symbol; @@ -158,14 +160,14 @@ class insn_info rtx src_symbol; unsigned dst_mem_addr; - unsigned src_intval; + unsigned src_mem_addr; public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const ( - false), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr ( - 0), src_intval (0) + false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol ( + 0), dst_mem_addr (0), src_mem_addr (0) { } @@ -179,7 +181,7 @@ class insn_info swap_adds (rtx_insn * newinsn, insn_info & ii); void - absolute2base (unsigned regno, unsigned base); + absolute2base (unsigned regno, unsigned base, rtx with_symbol); inline bool is_dst_reg () const @@ -205,18 +207,35 @@ class insn_info return dst_mem_reg; } + inline bool + has_src_memreg () const + { + return src_mem_reg; + } + inline rtx get_dst_symbol () const { return dst_symbol; } + inline rtx + get_src_symbol () const + { + return src_symbol; + } inline bool has_dst_addr () const { return dst_mem_addr; } + inline bool + has_src_addr () const + { + return src_mem_addr; + } + inline bool is_label () const { @@ -241,6 +260,12 @@ class insn_info return dst_mem_addr; } + inline unsigned + get_src_addr () const + { + return src_mem_addr; + } + inline bool is_src_reg () const { @@ -292,7 +317,7 @@ class insn_info inline int get_src_intval () const { - return src_intval; + return src_mem_addr; } inline bool @@ -401,6 +426,12 @@ class insn_info return use; } + inline unsigned + get_myuse () const + { + return myuse; + } + inline void set_use (unsigned u) { @@ -467,6 +498,7 @@ class insn_info inline insn_info & merge (insn_info const & o) { + myuse = o.myuse; use = (use & ~o.def) | o.use; def |= o.def; hard |= o.hard; @@ -577,6 +609,8 @@ class insn_info void set_insn (rtx_insn * newinsn); + void + a5_to_a7 (rtx a7); }; void @@ -677,6 +711,8 @@ insn_info::fledder (rtx set) rtx dst = SET_DEST(set); rtx src = SET_SRC(set); + mode = GET_MODE(dst); + if (dst == cc0_rtx) { compare = true; @@ -737,7 +773,7 @@ insn_info::fledder (rtx set) if (REG_P(mem)) src_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) - src_intval = INTVAL(mem); + src_mem_addr = INTVAL(mem); else if (GET_CODE(mem) == SYMBOL_REF) src_symbol = mem; else if (GET_CODE(mem) == PLUS) @@ -749,7 +785,7 @@ insn_info::fledder (rtx set) { src_mem_reg = reg; src_const = true; - src_intval = INTVAL(konst); + src_mem_addr = INTVAL(konst); } } else if (GET_CODE(mem) == CONST) @@ -762,7 +798,7 @@ insn_info::fledder (rtx set) { src_plus = true; src_symbol = sym; - src_intval = INTVAL(XEXP(mem, 1)); + src_mem_addr = INTVAL(XEXP(mem, 1)); } } } @@ -770,7 +806,7 @@ insn_info::fledder (rtx set) else if (GET_CODE(src) == CONST_INT) { src_const = true; - src_intval = INTVAL(src); + src_mem_addr = INTVAL(src); } else if (GET_CODE(src) == PLUS) { @@ -783,7 +819,7 @@ insn_info::fledder (rtx set) { src_reg = reg; src_const = true; - src_intval = INTVAL(konst); + src_mem_addr = INTVAL(konst); } else if (REG_P(konst)) { @@ -915,6 +951,42 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii) // usage flags did not change } +static +void +replace_reg (rtx x, unsigned regno, rtx newreg, int offset) +{ + RTX_CODE code = GET_CODE(x); + const char *fmt = GET_RTX_FORMAT(code); + for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + { + rtx y = XEXP(x, i); + if (REG_P(y) && REGNO(y) == regno) + { + XEXP(x, i) = newreg; + if (offset && i + 1 < GET_RTX_LENGTH(code)) + { + rtx c = XEXP(x, i + 1); + if (GET_CODE(c) == CONST_INT) + XEXP(x, i + 1) = gen_rtx_CONST_INT (GET_MODE(x), INTVAL(c) + offset); + } + } + else + replace_reg (y, regno, newreg, offset); + } + else if (fmt[i] == 'E') + for (int j = XVECLEN (x, i) - 1; j >= 0; j--) + replace_reg (XVECEXP(x, i, j), regno, newreg, offset); + } +} + +void +insn_info::a5_to_a7 (rtx a7) +{ + replace_reg (PATTERN (insn), FRAME_POINTER_REGNUM, a7, -4); +} + void insn_info::set_insn (rtx_insn * newinsn) { @@ -923,32 +995,63 @@ insn_info::set_insn (rtx_insn * newinsn) } void -insn_info::absolute2base (unsigned regno, unsigned base) +insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) { rtx set = PATTERN (get_insn ()); rtx src = SET_SRC(set); - machine_mode mode = GET_MODE(SET_DEST(set)); - - unsigned addr = get_dst_addr (); - unsigned offset = addr - base; + rtx dst = SET_DEST(set); + machine_mode mode = GET_MODE(dst); rtx pattern; rtx reg = gen_raw_REG (SImode, regno); - if (base == addr) - pattern = gen_rtx_SET(gen_rtx_MEM (mode, reg), src); - else - pattern = gen_rtx_SET(gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT(SImode, offset))), src); + + if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol) + { + unsigned addr = get_dst_addr (); + unsigned offset = addr - base; + if (offset <= 0x7ffe) + { + rtx olddst = dst; + if (base == addr) + dst = gen_rtx_MEM (mode, reg); + else + dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + + if (src_plus && rtx_equal_p (olddst, XEXP(src, 0))) + XEXP(src, 0) = dst; + + dst_mem_reg = reg; + dst_mem = true; + dst_mem_addr = offset; + dst_plus = offset != 0; + } + } + + if (is_src_mem () && (has_src_addr () || get_src_symbol ()) && !has_src_memreg () && get_src_symbol () == with_symbol) + { + unsigned addr = get_src_addr (); + unsigned offset = addr - base; + if (offset <= 0x7ffe) + { + if (base == addr) + src = gen_rtx_MEM (mode, reg); + else + src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + + src_mem_reg = reg; + src_mem = true; + src_mem_addr = offset; + src_plus = offset != 0; + } + } + + pattern = gen_rtx_SET(dst, src); SET_INSN_DELETED(insn); insn = emit_insn_after (pattern, insn); mark_use (regno); - dst_mem_reg = reg; - dst_mem = true; - dst_mem_addr = offset; - dst_plus = offset != 0; - insn2index.insert (std::make_pair (insn, this)); } /* @@ -2646,29 +2749,29 @@ opt_shrink_stack_frame (void) if (usea5 && a5offset == -4) { + /* for now only drop the frame pointer if it's not used. + * Needs tracking of the sp to adjust the offsets. + */ if (freemask & (1 << FRAME_POINTER_REGNUM)) { log ("dropping unused frame pointer\n"); - for (std::vector::iterator i = a5pos.begin (); i != a5pos.end (); ++i) - SET_INSN_DELETED(infos[*i].get_insn ()); + for (auto i = a5pos.rbegin (); i != a5pos.rend (); ++i) + { + SET_INSN_DELETED(infos[*i].get_insn ()); + infos.erase (infos.begin () + *i); + } - /* convert parameter access via a5 into a7. */ + /* convert all parameter accesses via a5 into a7. */ for (unsigned i = 0; i < infos.size (); ++i) { insn_info & ii = infos[i]; + if (ii.get_myuse () & (1 << FRAME_POINTER_REGNUM)) + ii.a5_to_a7 (a7); - if (ii.is_dst_reg () && ii.get_src_mem_regno () == FRAME_POINTER_REGNUM) - { - rtx x = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - 4); - rtx p = gen_rtx_PLUS(SImode, a7, x); - rtx pattern = gen_rtx_SET(copy_reg (ii.get_dst_reg (), -1), - gen_rtx_MEM (GET_MODE(ii.get_dst_reg ()), p)); - set_insn_deleted (ii.get_insn ()); - rtx_insn * newinsn = emit_insn_after (pattern, ii.get_insn ()); - ii.plus_to_move (newinsn); - } + ii.unset (FRAME_POINTER_REGNUM); } + update_insn2index (); ++changed; } } @@ -2687,18 +2790,23 @@ opt_absolute (void) for (unsigned i = 0; i < infos.size (); ++i) { insn_info & ii = infos[i]; - if (!ii.is_dst_mem () || !ii.has_dst_addr () || ii.has_dst_memreg ()) + + bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg (); + bool is_src = ii.is_src_mem () && (ii.has_src_addr () || ii.get_src_symbol ()) && !ii.has_src_memreg (); + + if (!is_dst && !is_src) continue; unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs; if (!freemask) continue; - rtx with_symbol = ii.get_dst_symbol (); + rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol (); std::vector found; found.push_back (i); unsigned base = ii.get_dst_addr (); + unsigned max = base; unsigned j = i + 1; for (; j < infos.size (); ++j) { @@ -2710,13 +2818,49 @@ opt_absolute (void) if (!freemask) break; - if (jj.is_dst_mem () && jj.has_dst_addr () && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol) + bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg () + && jj.get_dst_symbol () == with_symbol; + bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg () + && jj.get_src_symbol () == with_symbol; + if (j_dst) { unsigned addr = jj.get_dst_addr (); if (addr < base) - base = addr; - - found.push_back (j); + { + if (max - addr <= 0x7ffe) + { + base = addr; + found.push_back (j); + continue; + } + } + else if (addr - base <= 0x7ffe) + { + if (addr > max) + max = addr; + found.push_back (j); + continue; + } + } + if (j_src) + { + unsigned addr = jj.get_src_addr (); + if (addr < base) + { + if (max - addr <= 0x7ffe) + { + base = addr; + found.push_back (j); + continue; + } + } + else if (addr - base <= 0x7ffe) + { + if (addr > max) + max = addr; + found.push_back (j); + continue; + } } } @@ -2743,7 +2887,7 @@ opt_absolute (void) for (auto k = found.begin (); k != found.end (); ++k) { insn_info & kk = infos[*k]; - kk.absolute2base (regno, base); + kk.absolute2base (regno, base, with_symbol); } // load base into reg @@ -2767,13 +2911,17 @@ opt_absolute (void) nn.fledder (lea); nn.mark_def (regno); infos.insert (infos.begin () + i, nn); - while (i++ < j) - infos[i].mark_use (regno); - ++j; + + /* mark until last hit is found. */ + for (unsigned k = i + 1; k < infos.size (); ++k) + { + infos[k].mark_use (regno); + if (k == *found.rbegin ()) + break; + } ++change_count; + --i; } - - i = j; } if (change_count) From 6e6ca44d77a0ac430aaa9d55181fada079ad76d1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 4 May 2017 14:59:26 +0200 Subject: [PATCH 110/303] @B fix cmp_sub --- gcc/bbb-opts.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a4bb1e0a97a3..568ce2a6543d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2192,14 +2192,17 @@ opt_const_cmp_to_sub (void) rtx jmppattern = PATTERN (patchme); - rtx jmpsrc = XEXP(jmppattern, 1); - if (!jmpsrc) + if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2) ok = false; - else if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + else { - rtx condition = XEXP(jmpsrc, 0); - RTX_CODE code = GET_CODE(condition); - ok = code == EQ || code == NE; + rtx jmpsrc = XEXP(jmppattern, 1); + if (GET_CODE(jmpsrc) == IF_THEN_ELSE) + { + rtx condition = XEXP(jmpsrc, 0); + RTX_CODE code = GET_CODE(condition); + ok = code == EQ || code == NE; + } } } } From bcacd054f6a8b47c7fa16580697a23fc0cd3393b Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 4 May 2017 22:59:56 +0200 Subject: [PATCH 111/303] @R opt_cmp_sub is now capable to replace a chain of compares --- .cproject | 4 + gcc/bbb-opts.c | 243 +++++++++++++++++++++++++++++++++------------------------ 2 files changed, 145 insertions(+), 102 deletions(-) diff --git a/.cproject b/.cproject index b3cddaefb27b..6db4cbe2447e 100755 --- .cproject +++ .cproject @@ -43,6 +43,7 @@ + @@ -58,6 +59,7 @@ + @@ -106,6 +108,7 @@ + @@ -119,6 +122,7 @@ + diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 568ce2a6543d..0d8ecedc7941 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -183,6 +183,18 @@ class insn_info void absolute2base (unsigned regno, unsigned base, rtx with_symbol); + inline bool + is_compare () const + { + return compare; + } + + inline machine_mode + get_mode () const + { + return mode; + } + inline bool is_dst_reg () const { @@ -387,6 +399,29 @@ class insn_info hard = 0; } + inline void + reset_flags () + { + compare = false; + dst_mem = false; + src_mem = false; + dst_plus = false; + src_plus = false; + src_const = false; + + mode = VOIDmode; + + dst_reg = 0; + dst_mem_reg = 0; + dst_symbol = 0; + src_reg = 0; + src_mem_reg = 0; + src_symbol = 0; + dst_mem_addr = 0; + + src_mem_addr = 0; + } + inline bool is_empty () { @@ -711,8 +746,6 @@ insn_info::fledder (rtx set) rtx dst = SET_DEST(set); rtx src = SET_SRC(set); - mode = GET_MODE(dst); - if (dst == cc0_rtx) { compare = true; @@ -721,6 +754,8 @@ insn_info::fledder (rtx set) src = SET_SRC(set); } + mode = GET_MODE(dst); + if (REG_P(dst)) { dst_reg = dst; @@ -991,6 +1026,9 @@ void insn_info::set_insn (rtx_insn * newinsn) { insn = newinsn; + + reset_flags (); + fledder (PATTERN (insn)); } @@ -1255,7 +1293,7 @@ update_insn_infos (void) /* fill the mask of general used regs. */ insn_info zz; - for (int i = 0; i < infos.size (); ++i) + for (unsigned i = 0; i < infos.size (); ++i) { insn_info & ii = infos[i]; if (ii.in_proepi () != 1) @@ -2097,140 +2135,141 @@ opt_const_cmp_to_sub (void) { unsigned change_count = 0; #if HAVE_cc0 - for (int index = infos.size () - 2; index > 0; --index) + if (infos.size () < 2) + return change_count; + + unsigned lastsub = 0; + for (unsigned index = infos.size () - 2; index > 0; --index) { - rtx_insn * insn = infos[index].get_insn (); - rtx seti = single_set (insn); - if (!seti) + insn_info & i1 = infos[index]; + + /* we wan't a compare or tst insn, */ + if (!i1.is_compare ()) continue; - rtx dsti = SET_DEST(seti); - if (dsti != cc0_rtx) + if (GET_MODE_SIZE(i1.get_mode()) > 4 || !i1.is_dst_reg () || REGNO(i1.get_dst_reg()) > 7) continue; - rtx srci = SET_SRC(seti); - if (GET_CODE(srci) != COMPARE) + /* src must be a reg dead register with a constant - or a #0 */ + if (!i1.get_src_reg () && (!i1.is_src_const () || i1.is_src_plus ())) continue; - rtx left = XEXP(srci, 0); - rtx right = XEXP(srci, 1); - if (!REG_P(left) || !REG_P(right) || REG_NREGS(left) > 1 || REG_NREGS(right) > 1) + /* allow an alive reg, if life ends at previous handled sub. */ + int lastsubval = 0; + if (lastsub == index + 3) + { + insn_info & pp = infos[lastsub]; + if (pp.get_dst_regno () != i1.get_dst_regno ()) + continue; + lastsubval = pp.get_src_intval (); + } + else if (!is_reg_dead (i1.get_dst_regno (), index)) continue; - // TODO - // FEATURE: check if the next uses are also a add/sub - // then maybe that add/sub can be adjusted too + insn_info & i0 = infos[index - 1]; + int intval = 0; + /* compare with register - check previous insn for load with constant. */ + if (i1.is_src_reg ()) + { + if (!is_reg_dead (i1.get_src_regno (), index)) + continue; -// if (!find_reg_note (insn, REG_DEAD, left) || !find_reg_note (insn, REG_DEAD, right)) -// continue; - /* use own reg_dead - reg_notes seem to be inaccurate!? */ - if (!is_reg_dead (REGNO(left), index) || !is_reg_dead (REGNO(right), index)) - continue; + if (GET_MODE_SIZE(i0.get_mode()) > 4) + continue; - // maybe add a search? - rtx_insn * prev = infos[index - 1].get_insn (); - rtx setp = single_set (prev); - if (!setp) - continue; + if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.is_src_plus ())) + continue; - rtx constant_reg = SET_DEST(setp); - if (!REG_P(constant_reg)) - continue; + if (i0.get_dst_regno () != i1.get_src_regno ()) + continue; - rtx srcp = SET_SRC(setp); - if (!CONST_INT_P(srcp)) - continue; + intval = -i0.get_src_intval (); + if (intval < -8 || intval > 7) + continue; - int intval = -INTVAL(srcp); - if (intval < -8 || intval > 7 || intval == 0) - continue; + /* is the next sub value in range? */ + if (lastsub == index + 3 && (lastsubval - intval < -8 || lastsubval - intval > 7)) + continue; + } - enum machine_mode mode = GET_MODE(constant_reg); - if (GET_MODE_SIZE(mode) > 4) + /* next insn must be the jump. */ + insn_info & i2 = infos[index + 1]; + if (!i2.is_jump ()) continue; - // printf("mode size: %d\n", GET_MODE_SIZE(mode)); + rtx_insn * jump = i2.get_insn (); + rtx jmppattern = PATTERN (jump); + if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2) + continue; - rtx reg = constant_reg == left ? right : constant_reg == right ? left : 0; + rtx jmpsrc = XEXP(jmppattern, 1); + if (GET_CODE(jmpsrc) != IF_THEN_ELSE) + continue; - // no gain with address regs. - if (!reg || REGNO(reg) > 7) + rtx condition = XEXP(jmpsrc, 0); + RTX_CODE code = GET_CODE(condition); + if (code != EQ && code != NE) continue; - // search the jump(s) - bool ok = true; + if (intval) { - // invert all conditions using this statement. - std::vector todo; - std::vector done; - done.resize (infos.size ()); - todo.push_back (index + 1); + rtx copyreg = copy_reg (i1.get_dst_reg (), -1); + /* create the sub statement. */ + rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval)); - while (ok && todo.size ()) - { - unsigned pos = todo[todo.size () - 1]; - todo.pop_back (); + rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub)); - if (done[pos]) - continue; + int num_clobbers_to_add = 0; + int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add); + if (insn_code_number < 0 || !check_asm_operands (PATTERN (subinsn))) + continue; - done[pos] = 1; + /* delete move #x,dy. */ + SET_INSN_DELETED(i0.get_insn ()) + /* delete cmp dx,dy */ + SET_INSN_DELETED(i1.get_insn ()); + /* add a cmp #0 - to be removed in final() */ - if (infos[pos].is_def (FIRST_PSEUDO_REGISTER)) - continue; + /* convert cmp/tst into sub */ + subinsn = emit_insn_before (PATTERN (subinsn), i1.get_insn ()); + i1.set_insn (subinsn); - if (pos + 1 < infos.size ()) - todo.push_back (pos + 1); + rtx neu = gen_rtx_SET(cc0_rtx, + gen_rtx_COMPARE(i1.get_mode (), copyreg, gen_rtx_CONST_INT(i1.get_mode (), 0))); - rtx_insn * patchme = infos[pos].get_insn (); - if (!JUMP_P(patchme)) - continue; + emit_insn_before (neu, i2.get_insn ()); - auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(patchme)); - if (j != insn2index.end ()) - todo.push_back (j->second->get_index ()); + log ("const_cmp_to_sub replaced %s == %s (%d) with sub %d,%s\n", reg_names[i1.get_dst_regno ()], + reg_names[i0.get_dst_regno ()], + -intval, -intval, reg_names[i1.get_dst_regno ()]); - rtx jmppattern = PATTERN (patchme); + if (index + 3 == lastsub) + { + /* patch previous sub - or even a compare. */ + insn_info & pp = infos[lastsub]; + + int diff = lastsubval - intval; + rtx c = gen_rtx_CONST_INT (i1.get_mode (), diff); - if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2) - ok = false; + if (pp.is_compare ()) + { + /* still a compare with 0 -> insert the sub. */ + rtx copyreg = copy_reg (i1.get_dst_reg (), -1); + /* create the sub statement. */ + rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, c); + rtx set = gen_rtx_SET(copyreg, sub); + emit_insn_before (set, pp.get_insn ()); + } else { - rtx jmpsrc = XEXP(jmppattern, 1); - if (GET_CODE(jmpsrc) == IF_THEN_ELSE) - { - rtx condition = XEXP(jmpsrc, 0); - RTX_CODE code = GET_CODE(condition); - ok = code == EQ || code == NE; - } + /* modify the sub. */ + XEXP(SET_SRC(PATTERN(pp.get_insn())), 1) = c; } } - } - if (!ok) - continue; - - rtx plus = gen_rtx_PLUS(mode, copy_reg (reg, -1), gen_rtx_CONST_INT (mode, intval)); - rtx_insn * neuprev = make_insn_raw (gen_rtx_SET(copy_reg (reg, -1), plus)); - - int num_clobbers_to_add = 0; - int insn_code_number = recog (PATTERN (neuprev), neuprev, &num_clobbers_to_add); - if (insn_code_number < 0 || !check_asm_operands (PATTERN (neuprev))) - continue; - - // also convert current statement to cmp #0, reg - SET_INSN_DELETED(insn); - rtx copyreg = copy_reg (reg, -1); - rtx neu = gen_rtx_SET(cc0_rtx, gen_rtx_COMPARE(mode, copyreg, gen_rtx_CONST_INT(mode, 0))); - insn = emit_insn_after (neu, prev); - add_reg_note (insn, REG_DEAD, copyreg); - - SET_INSN_DELETED(prev); - prev = emit_insn_before (PATTERN (neuprev), insn); - - log ("const_cmp_to_sub replaced reg-reg compare with sub\n"); - - ++change_count; + lastsub = index; + ++change_count; + } } #endif return change_count; @@ -2992,7 +3031,7 @@ namespace pass_bbb_optimizations::execute_bbb_optimizations (void) { be_very_verbose = strchr (string_bbb_opts, 'V'); - be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1; + be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v'); bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); From 92278608b8be02dd6fc699e0ea912e12e3047a23 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 7 May 2017 17:50:45 +0200 Subject: [PATCH 112/303] @B opt_absolute now only touches insns with a valid mode. --- gcc/bbb-opts.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 0d8ecedc7941..e6ff270e8837 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -755,6 +755,8 @@ insn_info::fledder (rtx set) } mode = GET_MODE(dst); + if (mode == VOIDmode) + mode = GET_MODE(src); if (REG_P(dst)) { @@ -1038,7 +1040,6 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) rtx set = PATTERN (get_insn ()); rtx src = SET_SRC(set); rtx dst = SET_DEST(set); - machine_mode mode = GET_MODE(dst); rtx pattern; rtx reg = gen_raw_REG (SImode, regno); @@ -2839,6 +2840,9 @@ opt_absolute (void) if (!is_dst && !is_src) continue; + if (ii.get_mode() == VOIDmode) + continue; + unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs; if (!freemask) continue; @@ -2860,6 +2864,9 @@ opt_absolute (void) if (!freemask) break; + if (jj.get_mode() == VOIDmode) + continue; + bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol; bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg () From 1e4de684a62e18bcb9655cbc1029c24dd426fcb5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 9 May 2017 19:40:17 +0200 Subject: [PATCH 113/303] @R be more compatible to different gcc versions replaced auto with explicite types --- gcc/bbb-opts.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 0d8ecedc7941..c1e3f247335f 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -923,6 +923,9 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr static std::vector infos; static std::vector jumps; static std::map insn2index; +typedef std::vector::iterator insn_info_iterator; +typedef std::vector::iterator rtx_insn_iterator; +typedef std::map::iterator i2i_iterator; static insn_info * info0; static unsigned usable_regs; @@ -1130,7 +1133,7 @@ void append_reg_usage (FILE * f, rtx_insn * insn) { - auto i = insn2index.find (insn); + i2i_iterator i = insn2index.find (insn); if (i == insn2index.end ()) return; @@ -1238,11 +1241,11 @@ update_insn_infos (void) if (LABEL_P(insn)) { /* work on all jumps referring to that label. */ - for (auto i = jumps.begin (); i != jumps.end (); ++i) + for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i) { if (JUMP_LABEL(*i) == insn) { - auto j = insn2index.find (*i); + i2i_iterator j = insn2index.find (*i); if (j != insn2index.end ()) todo.push_back (std::make_pair (j->second->get_index (), ii)); } @@ -1481,11 +1484,11 @@ opt_reg_rename (void) * check if the reg was used at that jump. * if used, find def */ - for (auto i = jumps.begin (); i != jumps.end (); ++i) + for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i) { if (JUMP_LABEL(*i) == insn) { - auto j = insn2index.find (*i); + i2i_iterator j = insn2index.find (*i); if (j == insn2index.end ()) continue; @@ -1528,7 +1531,7 @@ opt_reg_rename (void) /* follow jump and/or next insn. */ if (JUMP_P(insn)) { - auto j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); + i2i_iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); if (j == insn2index.end ()) { /* whoops - label not found. */ @@ -2797,7 +2800,7 @@ opt_shrink_stack_frame (void) if (freemask & (1 << FRAME_POINTER_REGNUM)) { log ("dropping unused frame pointer\n"); - for (auto i = a5pos.rbegin (); i != a5pos.rend (); ++i) + for (std::vector::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i) { SET_INSN_DELETED(infos[*i].get_insn ()); infos.erase (infos.begin () + *i); @@ -2909,7 +2912,7 @@ opt_absolute (void) if (freemask && found.size () > 2) { /* check again. */ - for (auto k = found.begin (); k != found.end ();) + for (std::vector::iterator k = found.begin (); k != found.end ();) { insn_info & kk = infos[*k]; if (kk.get_dst_addr () - base > 0x7ffc) @@ -2926,7 +2929,7 @@ opt_absolute (void) else log ("modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]); - for (auto k = found.begin (); k != found.end (); ++k) + for (std::vector::iterator k = found.begin (); k != found.end (); ++k) { insn_info & kk = infos[*k]; kk.absolute2base (regno, base, with_symbol); From 3625786a260599ad20349b8bd22cc88ad90fecb0 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 12 May 2017 22:17:41 +0200 Subject: [PATCH 114/303] @I remove eclipse specific defines --- gcc/bbb-opts.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index c1e3f247335f..77e7f71f3b47 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -74,15 +74,6 @@ bool be_very_verbose; bool be_verbose; -#ifdef __ECLIPSE__ -//extern char * string_bbb_opts; -#define FIRST_PSEUDO_REGISTER 25 -#define FRAME_POINTER_REGNUM 13 -#define STACK_POINTER_REGNUM 15 -#define NOTICE_UPDATE_CC(a,b) -#define Pmode SImode -#define PIC_REG 12 -#endif extern struct lang_hooks lang_hooks; /* Lookup of the current function name. */ From e43aec51a54659db8760159c651a27b4efb88580 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 13 May 2017 23:06:49 +0200 Subject: [PATCH 115/303] @B avoid lea into data regs - enforce constraints --- gcc/config/m68k/constraints.md | 6 ++++++ gcc/config/m68k/m68k.md | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md index b62120895304..94a785dc95b6 100644 --- gcc/config/m68k/constraints.md +++ gcc/config/m68k/constraints.md @@ -97,6 +97,12 @@ (match_test "!TARGET_PCREL") (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)"))) +(define_constraint "t" + "Used for operands that satisfy 's' without PIC stuff, when -mpcrel is not in effect." + (and (match_code "symbol_ref,label_ref,const") + (match_test "!TARGET_PCREL") + (match_test "!flag_pic || GET_CODE(op) != CONST || GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF"))) + (define_memory_constraint "Q" "Means address register indirect addressing mode." (and (match_code "mem") diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 24332476b91b..d5ab0cfab8c8 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -955,8 +955,8 @@ (define_insn "*movsi_m68k" ;; Notes: make sure no alternative allows g vs g. ;; We don't allow f-regs since fixed point cannot go in them. - [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<") - (match_operand:SI 1 "general_src_operand" "damSnT,n,i"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<") + (match_operand:SI 1 "general_src_operand" "damSnt,T,n,i"))] "!TARGET_COLDFIRE && reload_completed" { return output_move_simode (operands); @@ -966,8 +966,8 @@ ;; force integer constants in range for a moveq to be reloaded ;; if they are headed for memory. (define_insn "*movsi_m68k2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<") - (match_operand:SI 1 "general_src_operand" "damSKT,n,i"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<") + (match_operand:SI 1 "general_src_operand" "damSKt,T,n,i"))] "!TARGET_COLDFIRE" { From 4a3f28381185450e2ceeafa657032690420a66ab Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 13 May 2017 23:07:46 +0200 Subject: [PATCH 116/303] @B use fresh insns instead of modifying old ones in opt_strcpy() --- gcc/bbb-opts.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index e6ff270e8837..f4dfb6177260 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1963,8 +1963,8 @@ opt_strcpy () int num_clobbers_to_add = 0; int insn_code_number; - rtx_insn * newinsn = make_insn_raw ( - gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg)))); + rtx pattern = gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg))); + rtx_insn * newinsn = make_insn_raw (pattern); insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add); if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn))) { @@ -1973,18 +1973,10 @@ opt_strcpy () log ("opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", reg_names[REGNO(dst)]); - SET_SRC(single_set(reg2x)) = SET_SRC(single_set (x2reg)); - - for (link = REG_NOTES(x2reg); link; link = XEXP(link, 1)) - if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) - { - if (GET_CODE (link) == EXPR_LIST) - add_reg_note (reg2x, REG_NOTE_KIND(link), copy_insn_1 (XEXP(link, 0))); - else - add_shallow_copy_of_reg_note (reg2x, link); - } + emit_insn_after(pattern, reg2x); SET_INSN_DELETED(x2reg); + SET_INSN_DELETED(reg2x); SET_INSN_DELETED(insn); ++change_count; From 03bac6a165016f2c667087d2f5102d2bc2cb897c Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 13 May 2017 23:34:25 +0200 Subject: [PATCH 117/303] @B exclude some operations and compares in opt_absolute() --- gcc/bbb-opts.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f4dfb6177260..ff7532281630 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2826,6 +2826,9 @@ opt_absolute (void) { insn_info & ii = infos[i]; + if (ii.is_compare()) + continue; + bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg (); bool is_src = ii.is_src_mem () && (ii.has_src_addr () || ii.get_src_symbol ()) && !ii.has_src_memreg (); @@ -2839,6 +2842,14 @@ opt_absolute (void) if (!freemask) continue; + rtx pattern = PATTERN(ii.get_insn()); + if (is_dst && !ii.get_src_reg() && !ii.is_src_const()) + if (MEM_P(XEXP(XEXP(pattern, 1), 0))) + continue; + if (is_src && !ii.get_dst_reg()) + if (MEM_P(XEXP(XEXP(pattern, 0), 0))) + continue; + rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol (); std::vector found; @@ -2856,13 +2867,22 @@ opt_absolute (void) if (!freemask) break; - if (jj.get_mode() == VOIDmode) + if (jj.get_mode() == VOIDmode || jj.is_compare()) continue; bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol; bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg () && jj.get_src_symbol () == with_symbol; + + pattern = PATTERN(jj.get_insn()); + if (j_dst && !jj.get_src_reg() && !jj.is_src_const()) + if (MEM_P(XEXP(XEXP(pattern, 1), 0))) + continue; + if (j_src && !jj.get_dst_reg()) + if (MEM_P(XEXP(XEXP(pattern, 0), 0))) + continue; + if (j_dst) { unsigned addr = jj.get_dst_addr (); From 9e1dd52e9e1bdb1ca9af945c5853b9d5b3a9fb46 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 15 May 2017 11:06:25 +0200 Subject: [PATCH 118/303] @B fix #20: handle subrge/strict_low_part in (b) --- gcc/DATESTAMP | 2 +- gcc/bbb-opts.c | 103 +++++++++++++++++++++++++++++++-------------------------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 59aff9a1ff47..2f2212531db5 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170430 +20170515 diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ff7532281630..ebae14f41832 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -148,6 +148,7 @@ class insn_info bool src_mem; bool dst_plus; bool src_plus; + int src_op; bool src_const; machine_mode mode; @@ -165,7 +166,7 @@ class insn_info public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( - false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_const ( + false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (0), src_const ( false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol ( 0), dst_mem_addr (0), src_mem_addr (0) { @@ -281,13 +282,13 @@ class insn_info inline bool is_src_reg () const { - return src_reg && !src_plus; + return src_reg && !src_op; } - inline bool - is_src_plus () const + inline int + get_src_op () const { - return src_reg && src_plus; + return src_op; } inline bool @@ -407,6 +408,7 @@ class insn_info src_mem = false; dst_plus = false; src_plus = false; + src_op = 0; src_const = false; mode = VOIDmode; @@ -754,6 +756,9 @@ insn_info::fledder (rtx set) src = SET_SRC(set); } + if (GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG) + dst = XEXP(dst, 0); + mode = GET_MODE(dst); if (mode == VOIDmode) mode = GET_MODE(src); @@ -845,22 +850,26 @@ insn_info::fledder (rtx set) src_const = true; src_mem_addr = INTVAL(src); } - else if (GET_CODE(src) == PLUS) + /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */ + if (*GET_RTX_FORMAT(GET_CODE(src)) == 'e') { - src_plus = true; + src_op = GET_CODE(src); rtx reg = XEXP(src, 0); - rtx konst = XEXP(src, 1); - if (REG_P(reg)) + if (REG_P(reg) && GET_RTX_LENGTH(GET_CODE(src)) >= 2) { - if (GET_CODE(konst) == CONST_INT) + rtx konst = XEXP(src, 1); + src_reg = reg; + if (konst) { - src_reg = reg; - src_const = true; - src_mem_addr = INTVAL(konst); - } - else if (REG_P(konst)) - { - src_reg = konst; + if (GET_CODE(konst) == CONST_INT) + { + src_const = true; + src_mem_addr = INTVAL(konst); + } + else if (REG_P(konst)) + { + src_reg = konst; /* dst_reg = dst_reg OP src_reg: store src_reg not dst_reg */ + } } } } @@ -969,7 +978,7 @@ void insn_info::plus_to_move (rtx_insn * newinsn) { insn = newinsn; - src_plus = false; + src_op = 0; src_reg = XEXP(PATTERN (newinsn), 1); insn2index.insert (std::make_pair (insn, this)); // usage flags did not change @@ -1603,7 +1612,7 @@ opt_reg_rename (void) if (!ok) continue; - log ("opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], + log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], patch.size (), index); /* apply all changes. */ @@ -1846,7 +1855,7 @@ opt_propagate_moves () rtx_insn * after = infos[index + 1].get_insn (); rtx bset = single_set (before); - log ("propagate_moves condition met, moving regs %s, %s\n", + log ("(p) propagate_moves condition met, moving regs %s, %s\n", reg_names[REGNO(srci)], reg_names[REGNO(dsti)]); @@ -1882,7 +1891,7 @@ opt_propagate_moves () /* add fixes if there were jumps out of the loop. */ if (jump_out.size ()) { - log ("propagate_moves fixing %d jump outs\n", jump_out.size ()); + log ("(p) propagate_moves fixing %d jump outs\n", jump_out.size ()); for (unsigned k = 0; k < jump_out.size (); ++k) { @@ -1970,10 +1979,10 @@ opt_strcpy () { rtx link; - log ("opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", + log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", reg_names[REGNO(dst)]); - emit_insn_after(pattern, reg2x); + emit_insn_after (pattern, reg2x); SET_INSN_DELETED(x2reg); SET_INSN_DELETED(reg2x); @@ -2086,7 +2095,7 @@ opt_commute_add_move (void) if (validate_change (next, &SET_DEST(set2), newmem, 0)) { - log ("commute_add_move found\n"); + log ("(a) commute_add_move found\n"); SET_INSN_DELETED(insn); @@ -2144,7 +2153,7 @@ opt_const_cmp_to_sub (void) continue; /* src must be a reg dead register with a constant - or a #0 */ - if (!i1.get_src_reg () && (!i1.is_src_const () || i1.is_src_plus ())) + if (!i1.get_src_reg () && (!i1.is_src_const () || i1.get_src_op () == PLUS)) continue; /* allow an alive reg, if life ends at previous handled sub. */ @@ -2170,7 +2179,7 @@ opt_const_cmp_to_sub (void) if (GET_MODE_SIZE(i0.get_mode()) > 4) continue; - if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.is_src_plus ())) + if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.get_src_op () == PLUS)) continue; if (i0.get_dst_regno () != i1.get_src_regno ()) @@ -2232,7 +2241,7 @@ opt_const_cmp_to_sub (void) emit_insn_before (neu, i2.get_insn ()); - log ("const_cmp_to_sub replaced %s == %s (%d) with sub %d,%s\n", reg_names[i1.get_dst_regno ()], + log ("(c) const_cmp_to_sub replaced %s == %s (%d) with sub %d,%s\n", reg_names[i1.get_dst_regno ()], reg_names[i0.get_dst_regno ()], -intval, -intval, reg_names[i1.get_dst_regno ()]); @@ -2293,7 +2302,7 @@ opt_elim_dead_assign (void) if (is_reg_dead (REGNO(dst), index)) { - log ("%d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]); + log ("(e) %d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); ++change_count; } @@ -2333,7 +2342,7 @@ opt_merge_add (void) continue; } - if (!ii0.is_dst_reg () || !ii0.is_src_plus () || !ii1.is_src_plus () || !ii2.is_src_plus ()) + if (!ii0.is_dst_reg () || ii0.get_src_op () != PLUS || ii1.get_src_op () != PLUS || ii2.get_src_op () != PLUS) continue; if (!ii0.is_src_const () || !ii2.is_src_const () || ii0.get_src_intval () != ii2.get_src_intval ()) @@ -2349,7 +2358,7 @@ opt_merge_add (void) if (cc_status.value1 || cc_status.value2) continue; - log ("%d: merge_add applied\n", index); + log ("(m) %d: merge_add applied\n", index); rtx_insn * insn0 = ii0.get_insn (); rtx set = PATTERN (insn0); @@ -2610,7 +2619,7 @@ opt_shrink_stack_frame (void) unsigned regbit = 1 << REGNO(reg); if (freemask & regbit) { - log (i < prologueend ? "remove push for %s\n" : "remove pop for %s\n", + log (i < prologueend ? "(f) remove push for %s\n" : "(f) remove pop for %s\n", reg_names[REGNO(reg)]); if (i < prologueend) adjust += 4; @@ -2631,7 +2640,7 @@ opt_shrink_stack_frame (void) int add1 = i < prologueend || !usea5 ? 1 : 0; if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2) { - log ("shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); + log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); if (regs.size () <= 2) { changed = 1; @@ -2726,7 +2735,7 @@ opt_shrink_stack_frame (void) if (freemask & regbit) { adjust += REGNO(src) > STACK_POINTER_REGNUM ? 12 : 4; - log ("remove push for %s\n", reg_names[REGNO(src)]); + log ("(f) remove push for %s\n", reg_names[REGNO(src)]); SET_INSN_DELETED(insn); ++changed; } @@ -2738,7 +2747,7 @@ opt_shrink_stack_frame (void) unsigned regbit = 1 << REGNO(dst); if (freemask & regbit) { - log ("remove pop for %s\n", reg_names[REGNO(dst)]); + log ("(f) remove pop for %s\n", reg_names[REGNO(dst)]); SET_INSN_DELETED(insn); ++changed; } @@ -2789,7 +2798,7 @@ opt_shrink_stack_frame (void) */ if (freemask & (1 << FRAME_POINTER_REGNUM)) { - log ("dropping unused frame pointer\n"); + log ("(f) dropping unused frame pointer\n"); for (auto i = a5pos.rbegin (); i != a5pos.rend (); ++i) { SET_INSN_DELETED(infos[*i].get_insn ()); @@ -2826,7 +2835,7 @@ opt_absolute (void) { insn_info & ii = infos[i]; - if (ii.is_compare()) + if (ii.is_compare ()) continue; bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg (); @@ -2835,18 +2844,19 @@ opt_absolute (void) if (!is_dst && !is_src) continue; - if (ii.get_mode() == VOIDmode) + if (ii.get_mode () == VOIDmode) continue; unsigned freemask = ~(ii.get_use () | ii.get_def ()) & 0x7f00 & usable_regs; if (!freemask) continue; - rtx pattern = PATTERN(ii.get_insn()); - if (is_dst && !ii.get_src_reg() && !ii.is_src_const()) + /* exclude operations on that symbol. */ + rtx pattern = PATTERN (ii.get_insn ()); + if (is_dst && !ii.get_src_reg () && !ii.is_src_const ()) if (MEM_P(XEXP(XEXP(pattern, 1), 0))) continue; - if (is_src && !ii.get_dst_reg()) + if (is_src && !ii.get_dst_reg ()) if (MEM_P(XEXP(XEXP(pattern, 0), 0))) continue; @@ -2867,7 +2877,7 @@ opt_absolute (void) if (!freemask) break; - if (jj.get_mode() == VOIDmode || jj.is_compare()) + if (jj.get_mode () == VOIDmode || jj.is_compare ()) continue; bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg () @@ -2875,11 +2885,12 @@ opt_absolute (void) bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg () && jj.get_src_symbol () == with_symbol; - pattern = PATTERN(jj.get_insn()); - if (j_dst && !jj.get_src_reg() && !jj.is_src_const()) + /* exclude operations on that symbol. */ + pattern = PATTERN (jj.get_insn ()); + if (j_dst && !jj.get_src_reg () && !jj.is_src_const ()) if (MEM_P(XEXP(XEXP(pattern, 1), 0))) continue; - if (j_src && !jj.get_dst_reg()) + if (j_src && !jj.get_dst_reg ()) if (MEM_P(XEXP(XEXP(pattern, 0), 0))) continue; @@ -2941,9 +2952,9 @@ opt_absolute (void) { unsigned regno = bit2regno (freemask); if (with_symbol) - log ("modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]); + log ("(b) modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]); else - log ("modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]); + log ("(b) modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]); for (auto k = found.begin (); k != found.end (); ++k) { From 7ad7dde941ed115c07b25ab998132282014b7141 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 15 May 2017 15:45:41 +0200 Subject: [PATCH 119/303] @R undo a stack frame change - no longer needed --- gcc/config/m68k/m68k.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 8a40cbc2ab1f..3b51b2541bc9 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -808,11 +808,9 @@ m68k_compute_frame_layout (void) /* Only compute the frame once per function. Don't cache information until reload has been completed. */ - /* SBF: No. Register renaming may free some variables, - * => compute it again and again... */ -// if (current_frame.funcdef_no == current_function_funcdef_no -// && reload_completed) -// return; + if (current_frame.funcdef_no == current_function_funcdef_no + && reload_completed) + return; current_frame.size = (get_frame_size () + 3) & -4; From 06d5805ee8035c3f8e32d7a14fb764bfbd9c2d83 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 15 May 2017 18:06:54 +0200 Subject: [PATCH 120/303] @B fix #19 - fix stack frame shrinking bugs --- gcc/bbb-opts.c | 100 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ebae14f41832..a997d721d605 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -88,10 +88,10 @@ extern struct lang_hooks lang_hooks; /* Lookup of the current function name. */ extern tree current_function_decl; static tree last_function_decl; +static char fxname[512]; static char const * get_current_function_name () { - static char fxname[512]; if (current_function_decl == NULL) strcpy (fxname, ""); else @@ -297,6 +297,12 @@ class insn_info return src_mem && src_plus; } + inline bool + is_dst_mem_plus () const + { + return dst_mem && dst_plus; + } + inline int get_dst_regno () const { @@ -327,12 +333,24 @@ class insn_info return src_mem_reg ? REGNO(src_mem_reg) : -1; } + inline int + get_dst_mem_regno () const + { + return dst_mem_reg ? REGNO(dst_mem_reg) : -1; + } + inline int get_src_intval () const { return src_mem_addr; } + inline int + get_dst_intval () const + { + return dst_mem_addr; + } + inline bool is_src_const () const { @@ -2587,6 +2605,12 @@ opt_shrink_stack_frame (void) /* check the pushed regs, either a vector or single statements */ if (GET_CODE(pattern) == PARALLEL) { + // do not touch the frame pointer parallel insn. + rtx set = XVECEXP(pattern, 0, 0); + rtx dst = SET_DEST(set); + if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) + continue; + std::vector regs; std::vector clobbers; for (int j = 0; j < XVECLEN(pattern, 0); ++j) @@ -2607,13 +2631,6 @@ opt_shrink_stack_frame (void) else continue; - if (REGNO(reg) == FRAME_POINTER_REGNUM) - { - // mark as "do not touch" - clobbers.push_back (reg); - break; - } - if (i < prologueend) paramstart += 4; unsigned regbit = 1 << REGNO(reg); @@ -2628,19 +2645,16 @@ opt_shrink_stack_frame (void) regs.push_back (copy_reg (reg, -1)); } - /* don't touch - clobbers! */ - if (clobbers.size ()) - continue; - - /* add romm for add. + /* add room for add. * push is always using -(a7) addressing. * If a5 is used a movem offset(a5) is generated to pop saved registers.. * Otherwise a7 is used and with (a7)+ addressing. */ int add1 = i < prologueend || !usea5 ? 1 : 0; - if ((int) regs.size () + add1 < XVECLEN(pattern, 0) || regs.size () <= 2) + if ((int) regs.size () + add1 + (int) clobbers.size () < XVECLEN(pattern, 0) || regs.size () <= 2) { - log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1, regs.size ()); + log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1 - clobbers.size (), + regs.size ()); if (regs.size () <= 2) { changed = 1; @@ -2674,17 +2688,19 @@ opt_shrink_stack_frame (void) for (unsigned k = 0; k < regs.size (); ++k) x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; + unsigned l = 0; /* no add if a5 is used with pop */ if (!usea5 || i < prologueend) { plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); - XVECEXP(parallel, 0, 0) = gen_rtx_SET(a7, plus); + XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus); + ++l; } if (i >= prologueend) x = usea5 ? -x : 0; - for (unsigned k = 0; k < regs.size (); ++k) + for (unsigned k = 0; k < regs.size (); ++k, ++l) { if (i < prologueend) { @@ -2693,7 +2709,7 @@ opt_shrink_stack_frame (void) x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); rtx set = gen_rtx_SET(mem, regs[k]); - XVECEXP(parallel, 0, k + 1) = set; + XVECEXP(parallel, 0, l) = set; } else { @@ -2704,7 +2720,7 @@ opt_shrink_stack_frame (void) plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); rtx set = gen_rtx_SET(regs[k], mem); - XVECEXP(parallel, 0, k) = set; + XVECEXP(parallel, 0, l) = set; } else { @@ -2712,10 +2728,16 @@ opt_shrink_stack_frame (void) x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); rtx set = gen_rtx_SET(regs[k], mem); - XVECEXP(parallel, 0, k + 1) = set; + XVECEXP(parallel, 0, l) = set; } } } + + for (unsigned k = 0; k < clobbers.size (); ++k) + { + rtx clobber = clobbers[k]; + XVECEXP(parallel, 0, l++) = clobber; + } emit_insn_after (parallel, insn); } SET_INSN_DELETED(insn); @@ -2761,32 +2783,19 @@ opt_shrink_stack_frame (void) for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; - insn = ii.get_insn (); - if (!insn || !INSN_P(insn)) - continue; - - rtx set = single_set (insn); - if (!set) - continue; + rtx pattern = PATTERN (ii.get_insn ()); + if (ii.is_compare ()) + pattern = XEXP(pattern, 1); + if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM) + { + rtx plus = XEXP(XEXP(pattern, 1), 0); + XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - adjust); + } - rtx mem = SET_SRC(set); - if (MEM_P(mem)) + if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM) { - rtx plus = XEXP(mem, 0); - if (GET_CODE(plus) == PLUS) - { - rtx sp = XEXP(plus, 0); - if (REG_P(sp) && REGNO(sp) == STACK_POINTER_REGNUM) - { - rtx c = XEXP(plus, 1); - if (CONST_INT_P(c)) - { - int n = INTVAL(c); - if (n >= paramstart) - XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, n - adjust); - } - } - } + rtx plus = XEXP(XEXP(pattern, 0), 0); + XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_dst_intval () - adjust); } } } @@ -3073,6 +3082,9 @@ namespace bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); + if (be_very_verbose) + log ("ENTER\n"); + for (;;) { int done = 1; From 6599877df5f8d490fbbc29a2509dd10137ebb0b4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 15 May 2017 22:20:22 +0200 Subject: [PATCH 121/303] @B fix #19 - renaming single registers of a register pair (long long) is a bad idea... --- gcc/bbb-opts.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index d0bef1dbc6dc..800f83ea40fe 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -649,6 +649,8 @@ class insn_info unsigned get_regbit () const { + if (GET_MODE_SIZE(mode) > 4) + return 0; return def & ~hard & ~use & 0x7fff; } @@ -1539,6 +1541,13 @@ opt_reg_rename (void) else if (!(jj.get_use () & rename_regbit)) break; + /* abort if some insn using this reg uses more than 1 reg. */ + if ((jj.get_myuse() & rename_regbit) && GET_MODE_SIZE(jj.get_mode()) > 4) + { + mask = 0; + break; + } + /* update free regs. */ mask &= ~jj.get_use (); mask &= ~jj.get_def (); From b35c1e12d6be7dfaf301801267ff558f6b149be5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 16 May 2017 12:47:15 +0200 Subject: [PATCH 122/303] @B fix recognition of asm function parameters --- gcc/BASE-VER | 2 +- gcc/DATESTAMP | 2 +- gcc/config/m68k/amigaos.c | 7 +++++++ gcc/config/m68k/amigaos.h | 20 -------------------- gcc/config/m68k/m68kamigaos.h | 18 ++++++++++++++++++ 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/gcc/BASE-VER b/gcc/BASE-VER index 76af0075384a..6352d5267189 100644 --- gcc/BASE-VER +++ gcc/BASE-VER @@ -1 +1 @@ -6.3.1d +6.3.1b diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2f2212531db5..43cf3b2286b6 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170515 +20170516 diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 419d59dc3871..3bd99b5c6389 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -463,6 +463,13 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); } + +int +amigaos_function_arg_reg(unsigned regno) +{ + return mycum.regs_already_used & (1 << regno) != 0; +} + /* Update the data in CUM to advance over an argument. */ void diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index e2a2b4cc11f6..284328683c37 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -381,31 +381,11 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP)) /* Note: this is an extension of m68k_args */ -/* A C type for declaring a variable that is used as the first - argument of `FUNCTION_ARG' and other related values. */ -/* Max. number of data, address and float registers to be used for passing - integer, pointer and float arguments when TARGET_REGPARM. - It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */ -#undef AMIGAOS_MAX_REGPARM -#define AMIGAOS_MAX_REGPARM 4 - -/* The default number of data, address and float registers to use when - user specified '-mregparm' switch, not '-mregparm=' option. */ -#undef AMIGAOS_DEFAULT_REGPARM -#define AMIGAOS_DEFAULT_REGPARM 2 - - #undef CLASS_MAX_NREGS #define CLASS_MAX_NREGS(CLASS, MODE) \ ((CLASS) == FP_REGS ? GET_MODE_NUNITS (MODE) \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) -/* 1 if N is a possible register number for function argument passing. */ -#undef FUNCTION_ARG_REGNO_P -#define FUNCTION_ARG_REGNO_P(N) \ - ((((int)N) >= 0 && (N) < AMIGAOS_MAX_REGPARM) \ - || ((N) >= 8 && (N) < 8 + AMIGAOS_MAX_REGPARM) \ - || (TARGET_68881 && (N) >= 16 && (N) < 16 + AMIGAOS_MAX_REGPARM)) /* On the m68k, this is a structure: diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 3ca2cd666e7c..f636e397cfca 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -670,3 +670,21 @@ extern int amiga_is_const_pic_ref(const_rtx x); #define EH_TABLES_CAN_BE_READ_ONLY 1 + +/* Max. number of data, address and float registers to be used for passing + integer, pointer and float arguments when TARGET_REGPARM. + It's 4, so d0-d3, a0-a3 and fp0-fp3 can be used. */ +#undef AMIGAOS_MAX_REGPARM +#define AMIGAOS_MAX_REGPARM 4 + +/* The default number of data, address and float registers to use when + user specified '-mregparm' switch, not '-mregparm=' option. */ +#undef AMIGAOS_DEFAULT_REGPARM +#define AMIGAOS_DEFAULT_REGPARM 2 + +/* 1 if N is a possible register number for function argument passing. */ +#undef FUNCTION_ARG_REGNO_P +#define FUNCTION_ARG_REGNO_P(N) amigaos_function_arg_reg(N) + +extern int +amigaos_function_arg_reg(unsigned regno); From 42f9687b3643a14d216c68b685a8b79f0e860c0e Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 16 May 2017 12:50:48 +0200 Subject: [PATCH 123/303] @B fix recognition of asm function parameters --- gcc/config/m68k/amigaos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 3bd99b5c6389..9166b91a69eb 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -467,7 +467,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) int amigaos_function_arg_reg(unsigned regno) { - return mycum.regs_already_used & (1 << regno) != 0; + return (mycum.regs_already_used & (1 << regno)) != 0; } /* Update the data in CUM to advance over an argument. */ From 97158247a4a2e85140f33ab30a1a8a8802744e64 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 17 May 2017 09:34:58 +0200 Subject: [PATCH 124/303] @B analyse jump_tables for correct flow and register usage analysis --- gcc/bbb-opts.c | 121 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 31 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 800f83ea40fe..e49148416a43 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -943,10 +943,12 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr * Collect some data. */ static std::vector infos; -static std::vector jumps; -static std::map insn2index; typedef std::vector::iterator insn_info_iterator; -typedef std::vector::iterator rtx_insn_iterator; + +static std::multimap label2jump; +typedef std::multimap::iterator l2j_iterator; + +static std::map insn2index; typedef std::map::iterator i2i_iterator; static insn_info * info0; @@ -1122,7 +1124,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) static void clear (void) { - jumps.clear (); + label2jump.clear (); insn2index.clear (); infos.clear (); } @@ -1154,7 +1156,7 @@ void append_reg_usage (FILE * f, rtx_insn * insn) { - i2i_iterator i = insn2index.find (insn); + i2i_iterator i = insn2index.find (insn); if (i == insn2index.end ()) return; @@ -1262,14 +1264,12 @@ update_insn_infos (void) if (LABEL_P(insn)) { /* work on all jumps referring to that label. */ - for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i) + for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i; + i != label2jump.end () && i->first == k->first; ++i) { - if (JUMP_LABEL(*i) == insn) - { - i2i_iterator j = insn2index.find (*i); - if (j != insn2index.end ()) - todo.push_back (std::make_pair (j->second->get_index (), ii)); - } + i2i_iterator j = insn2index.find (i->second); + if (j != insn2index.end ()) + todo.push_back (std::make_pair (j->second->get_index (), ii)); } continue; } @@ -1299,7 +1299,7 @@ update_insn_infos (void) if (!use.is_def (FIRST_PSEUDO_REGISTER)) { CC_STATUS_INIT; - NOTICE_UPDATE_CC (PATTERN (insn), insn); + NOTICE_UPDATE_CC(PATTERN (insn), insn); if (cc_status.value1 || cc_status.value2) use.mark_def (FIRST_PSEUDO_REGISTER); } @@ -1340,10 +1340,13 @@ update_insn_infos (void) /* * Create a filtered view of insns - keep only those to work with. */ -static void +static int update_insns () { rtx_insn *insn, *next; + + rtx jump_table = 0; + clear (); char inproepilogue = 1; @@ -1360,10 +1363,50 @@ update_insns () if (JUMP_P(insn)) { - jumps.push_back (insn); inproepilogue = 0; ii.mark_jump (); + + rtx pattern = PATTERN (insn); + if (GET_CODE(pattern) == PARALLEL) + { + /* + * Use the jump_table_data and add all to the lookup + */ + if (jump_table == 0) + { + // still allow complex if_then_else which are also in parallel + rtx ite = XVECEXP(insn, 0, 0); + if (XEXP(ite, 0) != pc_rtx || GET_CODE(XEXP(ite, 1)) != IF_THEN_ELSE) + { + debug_rtx(insn); + return 1; // do not optimize. + } + } + else + if (XEXP(jump_table, 0) != insn) + { + debug_rtx(insn); + return 2; + } + + // -> jump_table_data + rtx table = PATTERN (XEXP(jump_table, 1)); + for (int j = 0; j < XVECLEN(table, 1); ++j) + { + rtx ref = XVECEXP(table, 1, j); + rtx label = XEXP(ref, 0); + label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + } + + jump_table = 0; + } + else + { + rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn); + label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + } + } else if (LABEL_P(insn)) { @@ -1378,6 +1421,16 @@ update_insns () rtx set = single_set (insn); if (set) ii.fledder (set); + + for (rtx next, note = REG_NOTES(insn); note; note = next) + { + next = XEXP(note, 1); + if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND) + { + jump_table = XEXP(note, 0); + } + } + } } @@ -1392,6 +1445,8 @@ update_insns () update_insn2index (); update_insn_infos (); + + return 0; } /* convert the lowest set bit into a register number. */ @@ -1505,21 +1560,19 @@ opt_reg_rename (void) * check if the reg was used at that jump. * if used, find def */ - for (rtx_insn_iterator i = jumps.begin (); i != jumps.end (); ++i) + for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i; + i != label2jump.end () && i->first == k->first; ++i) { - if (JUMP_LABEL(*i) == insn) - { - i2i_iterator j = insn2index.find (*i); - if (j == insn2index.end ()) - continue; + i2i_iterator j = insn2index.find (i->second); + if (j == insn2index.end ()) + continue; - unsigned start = j->second->get_index (); - if (!infos[start].is_use (rename_regno)) - continue; + unsigned start = j->second->get_index (); + if (!infos[start].is_use (rename_regno)) + continue; - start = find_start (found, start, rename_regno); - todo.push_back (start); - } + start = find_start (found, start, rename_regno); + todo.push_back (start); } continue; } @@ -1542,7 +1595,7 @@ opt_reg_rename (void) break; /* abort if some insn using this reg uses more than 1 reg. */ - if ((jj.get_myuse() & rename_regbit) && GET_MODE_SIZE(jj.get_mode()) > 4) + if ((jj.get_myuse () & rename_regbit) && GET_MODE_SIZE(jj.get_mode()) > 4) { mask = 0; break; @@ -1987,7 +2040,7 @@ opt_strcpy () if (REG_P(dst) && CONST_INT_P(src) && INTVAL(src) == 0 && is_reg_dead (REGNO(dst), index)) { /* now check via NOTICE_UPDATE_CC*/ - NOTICE_UPDATE_CC (PATTERN (reg2x), reg2x); + NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x); if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2)) { int num_clobbers_to_add = 0; @@ -2375,7 +2428,7 @@ opt_merge_add (void) rtx_insn * insn1 = ii1.get_insn (); CC_STATUS_INIT; - NOTICE_UPDATE_CC (PATTERN (insn1), insn1); + NOTICE_UPDATE_CC(PATTERN (insn1), insn1); if (cc_status.value1 || cc_status.value2) continue; @@ -3091,7 +3144,13 @@ namespace for (;;) { int done = 1; - update_insns (); + int r = update_insns (); + if (r) + { + if (be_verbose) + log("no bbb optimization code %d\n", r); + return 0; + } if (do_opt_strcpy && opt_strcpy ()) done = 0, update_insns (); From d49f98c1822e1a810d81048c0082ebec69a5d66f Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 17 May 2017 11:12:25 +0200 Subject: [PATCH 125/303] @B support if_then_else inside of parallel insns --- gcc/DATESTAMP | 2 +- gcc/bbb-opts.c | 37 ++++++++++++++++++------------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 43cf3b2286b6..f9bb1bba46d4 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170516 +20170517 diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index e49148416a43..7fa077167ef2 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1375,30 +1375,32 @@ update_insns () */ if (jump_table == 0) { - // still allow complex if_then_else which are also in parallel - rtx ite = XVECEXP(insn, 0, 0); + // still allow if_then_else inside a parallel insn + rtx ite = XVECEXP(pattern, 0, 0); if (XEXP(ite, 0) != pc_rtx || GET_CODE(XEXP(ite, 1)) != IF_THEN_ELSE) { - debug_rtx(insn); + debug_rtx (insn); return 1; // do not optimize. } + rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn); + label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); } - else - if (XEXP(jump_table, 0) != insn) + else if (XEXP(jump_table, 0) != insn) { - debug_rtx(insn); + debug_rtx (insn); return 2; } - - // -> jump_table_data - rtx table = PATTERN (XEXP(jump_table, 1)); - for (int j = 0; j < XVECLEN(table, 1); ++j) + else { - rtx ref = XVECEXP(table, 1, j); - rtx label = XEXP(ref, 0); - label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + // -> jump_table_data + rtx table = PATTERN (XEXP(jump_table, 1)); + for (int j = 0; j < XVECLEN(table, 1); ++j) + { + rtx ref = XVECEXP(table, 1, j); + rtx label = XEXP(ref, 0); + label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + } } - jump_table = 0; } else @@ -1433,8 +1435,7 @@ update_insns () } } - - if (NOTE_P(insn)) + else if (NOTE_P(insn)) { if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) inproepilogue = 0; @@ -2051,8 +2052,6 @@ opt_strcpy () insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add); if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn))) { - rtx link; - log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", reg_names[REGNO(dst)]); @@ -3148,7 +3147,7 @@ namespace if (r) { if (be_verbose) - log("no bbb optimization code %d\n", r); + log ("no bbb optimization code %d\n", r); return 0; } if (do_opt_strcpy && opt_strcpy ()) From 7c4335944b40ed8cac718f17a3492b543589c1e9 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 17 May 2017 13:44:06 +0200 Subject: [PATCH 126/303] @B fix absolute optimization --- gcc/bbb-opts.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 7fa077167ef2..adc21bf4e39e 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1081,7 +1081,8 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) else dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); - if (src_plus && rtx_equal_p (olddst, XEXP(src, 0))) + /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */ + if (src_op && rtx_equal_p (olddst, XEXP(src, 0))) XEXP(src, 0) = dst; dst_mem_reg = reg; @@ -2950,13 +2951,6 @@ opt_absolute (void) && jj.get_src_symbol () == with_symbol; /* exclude operations on that symbol. */ - pattern = PATTERN (jj.get_insn ()); - if (j_dst && !jj.get_src_reg () && !jj.is_src_const ()) - if (MEM_P(XEXP(XEXP(pattern, 1), 0))) - continue; - if (j_src && !jj.get_dst_reg ()) - if (MEM_P(XEXP(XEXP(pattern, 0), 0))) - continue; if (j_dst) { From f89679a40f70cf28bfe2e5b9cec347b292df4d1c Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 17 May 2017 20:55:45 +0200 Subject: [PATCH 127/303] @B fix reading insn like lea 1(a0),a1 - to extract the correct source register --- gcc/bbb-opts.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index adc21bf4e39e..37fc9dbd01fc 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -815,6 +815,25 @@ insn_info::fledder (rtx set) } } + /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */ + rtx alt_src_reg = 0; + int code = GET_CODE(src); + if (!REG_P(src) && !MEM_P(src) && code != CONST_INT && code != CONST && code != CONST_WIDE_INT && code != CONST_DOUBLE + && code != CONST_FIXED && code != CONST_STRING) + { + src_op = GET_CODE(src); + const char *fmt = GET_RTX_FORMAT(code); + if (fmt[0] == 'e' && fmt[1] == 'e') + { + rtx operand = XEXP(src, 1); + if (GET_CODE(operand) == CONST_INT) + src_const = true, src_mem_addr = INTVAL(operand); + else if (REG_P(operand)) + alt_src_reg = operand; + } + src = XEXP(src, 0); + } + if (REG_P(src)) { src_reg = src; @@ -861,29 +880,8 @@ insn_info::fledder (rtx set) src_const = true; src_mem_addr = INTVAL(src); } - /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */ - if (*GET_RTX_FORMAT(GET_CODE(src)) == 'e') - { - src_op = GET_CODE(src); - rtx reg = XEXP(src, 0); - if (REG_P(reg) && GET_RTX_LENGTH(GET_CODE(src)) >= 2) - { - rtx konst = XEXP(src, 1); - src_reg = reg; - if (konst) - { - if (GET_CODE(konst) == CONST_INT) - { - src_const = true; - src_mem_addr = INTVAL(konst); - } - else if (REG_P(konst)) - { - src_reg = konst; /* dst_reg = dst_reg OP src_reg: store src_reg not dst_reg */ - } - } - } - } + if (alt_src_reg) + src_reg = alt_src_reg; } /* create a copy for a reg. Optional specify a new register number. */ @@ -2844,7 +2842,10 @@ opt_shrink_stack_frame (void) pattern = XEXP(pattern, 1); if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM) { - rtx plus = XEXP(XEXP(pattern, 1), 0); + rtx src = XEXP(pattern, 1); + rtx plus = XEXP(src, 0); + if (ii.get_src_op ()) + plus = XEXP(plus, 0); XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - adjust); } From aa46f14ae49b802ed71bc0fa238045089ede31da Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 17 May 2017 23:29:00 +0200 Subject: [PATCH 128/303] @B fix operations on symbol/absolute are now correctly converted int operations on address reg --- gcc/bbb-opts.c | 68 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 37fc9dbd01fc..5cce787b0d27 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -139,7 +139,8 @@ class insn_info bool src_mem; bool dst_plus; bool src_plus; - int src_op; + rtx_code src_op; + bool src_ee; bool src_const; machine_mode mode; @@ -151,15 +152,15 @@ class insn_info rtx src_mem_reg; rtx src_symbol; unsigned dst_mem_addr; - + int src_intval; unsigned src_mem_addr; public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( - false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op (0), src_const ( - false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol ( - 0), dst_mem_addr (0), src_mem_addr (0) + false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( + (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol ( + 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0) { } @@ -265,7 +266,7 @@ class insn_info } inline unsigned - get_src_addr () const + get_src_mem_addr () const { return src_mem_addr; } @@ -282,6 +283,12 @@ class insn_info return src_op; } + inline bool + is_src_ee () const + { + return src_ee; + } + inline bool is_src_mem_plus () const { @@ -333,7 +340,7 @@ class insn_info inline int get_src_intval () const { - return src_mem_addr; + return src_intval; } inline int @@ -417,7 +424,8 @@ class insn_info src_mem = false; dst_plus = false; src_plus = false; - src_op = 0; + src_op = (rtx_code)0; + src_ee = false; src_const = false; mode = VOIDmode; @@ -430,6 +438,7 @@ class insn_info src_symbol = 0; dst_mem_addr = 0; + src_intval = 0; src_mem_addr = 0; } @@ -818,16 +827,17 @@ insn_info::fledder (rtx set) /* It' some kind of operation, e.g. PLUS, XOR, NEG, ... */ rtx alt_src_reg = 0; int code = GET_CODE(src); - if (!REG_P(src) && !MEM_P(src) && code != CONST_INT && code != CONST && code != CONST_WIDE_INT && code != CONST_DOUBLE + if (!REG_P(src) && !MEM_P(src) && code != CONST_INT && code != CONST && code != CONST_WIDE_INT && code != CONST_DOUBLE && code != CONST_FIXED && code != CONST_STRING) { src_op = GET_CODE(src); const char *fmt = GET_RTX_FORMAT(code); if (fmt[0] == 'e' && fmt[1] == 'e') { + src_ee = true; rtx operand = XEXP(src, 1); - if (GET_CODE(operand) == CONST_INT) - src_const = true, src_mem_addr = INTVAL(operand); + if (GET_CODE(operand) == CONST_INT || GET_CODE(operand) == CONST_WIDE_INT) + src_const = true, src_intval = INTVAL(operand); else if (REG_P(operand)) alt_src_reg = operand; } @@ -992,7 +1002,7 @@ void insn_info::plus_to_move (rtx_insn * newinsn) { insn = newinsn; - src_op = 0; + src_op = (rtx_code)0; src_reg = XEXP(PATTERN (newinsn), 1); insn2index.insert (std::make_pair (insn, this)); // usage flags did not change @@ -1079,10 +1089,6 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) else dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); - /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */ - if (src_op && rtx_equal_p (olddst, XEXP(src, 0))) - XEXP(src, 0) = dst; - dst_mem_reg = reg; dst_mem = true; dst_mem_addr = offset; @@ -1092,7 +1098,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) if (is_src_mem () && (has_src_addr () || get_src_symbol ()) && !has_src_memreg () && get_src_symbol () == with_symbol) { - unsigned addr = get_src_addr (); + unsigned addr = get_src_mem_addr (); unsigned offset = addr - base; if (offset <= 0x7ffe) { @@ -1101,6 +1107,15 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) else src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */ + if (src_op) + { + if (src_ee) + src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval)); + else + src = gen_rtx_fmt_e(src_op, mode, src); + } + src_mem_reg = reg; src_mem = true; src_mem_addr = offset; @@ -2846,7 +2861,7 @@ opt_shrink_stack_frame (void) rtx plus = XEXP(src, 0); if (ii.get_src_op ()) plus = XEXP(plus, 0); - XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_intval () - adjust); + XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_mem_addr () - adjust); } if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM) @@ -2904,6 +2919,9 @@ opt_absolute (void) if (ii.is_compare ()) continue; + if (ii.get_src_op () && ii.is_src_ee () && !ii.get_src_intval ()) + continue; + bool is_dst = ii.is_dst_mem () && (ii.has_dst_addr () || ii.get_dst_symbol ()) && !ii.has_dst_memreg (); bool is_src = ii.is_src_mem () && (ii.has_src_addr () || ii.get_src_symbol ()) && !ii.has_src_memreg (); @@ -2917,15 +2935,6 @@ opt_absolute (void) if (!freemask) continue; - /* exclude operations on that symbol. */ - rtx pattern = PATTERN (ii.get_insn ()); - if (is_dst && !ii.get_src_reg () && !ii.is_src_const ()) - if (MEM_P(XEXP(XEXP(pattern, 1), 0))) - continue; - if (is_src && !ii.get_dst_reg ()) - if (MEM_P(XEXP(XEXP(pattern, 0), 0))) - continue; - rtx with_symbol = is_dst ? ii.get_dst_symbol () : ii.get_src_symbol (); std::vector found; @@ -2946,6 +2955,9 @@ opt_absolute (void) if (jj.get_mode () == VOIDmode || jj.is_compare ()) continue; + if (jj.get_src_op () && jj.is_src_ee () && !jj.get_src_intval ()) + continue; + bool j_dst = jj.is_dst_mem () && (jj.has_dst_addr () || jj.get_dst_symbol ()) && !jj.has_dst_memreg () && jj.get_dst_symbol () == with_symbol; bool j_src = jj.is_src_mem () && (jj.has_src_addr () || jj.get_src_symbol ()) && !jj.has_src_memreg () @@ -2975,7 +2987,7 @@ opt_absolute (void) } if (j_src) { - unsigned addr = jj.get_src_addr (); + unsigned addr = jj.get_src_mem_addr (); if (addr < base) { if (max - addr <= 0x7ffe) From edca4acf887636033d51096888e751820ef9718d Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 18 May 2017 00:00:26 +0200 Subject: [PATCH 129/303] @B fix opt_absolute for SIGN_EXTEND (ext.*) --- gcc/bbb-opts.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 5cce787b0d27..dd2923873c1d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1113,7 +1113,14 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) if (src_ee) src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval)); else - src = gen_rtx_fmt_e(src_op, mode, src); + { + if (src_op == SIGN_EXTEND) + { + PUT_MODE_RAW(src, mode == SImode ? HImode : mode == HImode ? QImode : SImode); + src->call = 1; + } + src = gen_rtx_fmt_e(src_op, mode, src); + } } src_mem_reg = reg; @@ -2945,12 +2952,17 @@ opt_absolute (void) for (; j < infos.size (); ++j) { insn_info & jj = infos[j]; - if (jj.is_label () || jj.is_jump () || jj.is_call ()) + /* TODO: continue also at jump target */ + if (jj.is_jump()) + continue; + /* TODO: check if label is visited only from jump targets from herein. then the label is ok. */ + if (jj.is_label ()) break; - freemask &= ~(jj.get_use () | jj.get_def ()); - if (!freemask) + unsigned tempmask = freemask & ~(jj.get_use () | jj.get_def ()); + if (!tempmask) break; + freemask = tempmask; if (jj.get_mode () == VOIDmode || jj.is_compare ()) continue; From 90e72be90df0d966c935ae3c91476af65f18cb81 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 20 May 2017 17:02:09 +0200 Subject: [PATCH 130/303] @B do not optimize with indirect jumps and unknown labels. @R doo not indicate regs for static_chain/struct_value if not used --- gcc/DATESTAMP | 2 +- gcc/bbb-opts.c | 151 ++++++++++++++++++++++++++-------------------- gcc/config/m68k/amigaos.c | 68 ++++++++++++--------- gcc/config/m68k/amigaos.h | 11 ++++ 4 files changed, 138 insertions(+), 94 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index f9bb1bba46d4..3f03e820cb0b 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170517 +20170520 diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index dd2923873c1d..848c18e3be52 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -424,7 +424,7 @@ class insn_info src_mem = false; dst_plus = false; src_plus = false; - src_op = (rtx_code)0; + src_op = (rtx_code) 0; src_ee = false; src_const = false; @@ -888,7 +888,7 @@ insn_info::fledder (rtx set) else if (GET_CODE(src) == CONST_INT) { src_const = true; - src_mem_addr = INTVAL(src); + src_intval = INTVAL(src); } if (alt_src_reg) src_reg = alt_src_reg; @@ -1002,7 +1002,7 @@ void insn_info::plus_to_move (rtx_insn * newinsn) { insn = newinsn; - src_op = (rtx_code)0; + src_op = (rtx_code) 0; src_reg = XEXP(PATTERN (newinsn), 1); insn2index.insert (std::make_pair (insn, this)); // usage flags did not change @@ -1358,14 +1358,19 @@ update_insn_infos (void) usable_regs &= ~(1 << STACK_POINTER_REGNUM); } +enum AbortCodes +{ + E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL +}; + /* * Create a filtered view of insns - keep only those to work with. */ -static int +static unsigned update_insns () { rtx_insn *insn, *next; - + unsigned result = 0; rtx jump_table = 0; clear (); @@ -1386,54 +1391,69 @@ update_insns () { inproepilogue = 0; - ii.mark_jump (); + if (ANY_RETURN_P(PATTERN (insn))) + continue; - rtx pattern = PATTERN (insn); - if (GET_CODE(pattern) == PARALLEL) + ii.mark_jump (); + if (jump_table) { - /* - * Use the jump_table_data and add all to the lookup - */ - if (jump_table == 0) + if (XEXP(jump_table, 0) != insn) { - // still allow if_then_else inside a parallel insn - rtx ite = XVECEXP(pattern, 0, 0); - if (XEXP(ite, 0) != pc_rtx || GET_CODE(XEXP(ite, 1)) != IF_THEN_ELSE) + if (be_very_verbose) { debug_rtx (insn); - return 1; // do not optimize. + debug_rtx (jump_table); } - rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn); - label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + result = E_JUMP_TABLE_MISMATCH; + jump_table = 0; + continue; } - else if (XEXP(jump_table, 0) != insn) + + // -> jump_table_data + rtx table = PATTERN (XEXP(jump_table, 1)); + if (GET_CODE(table) == ADDR_DIFF_VEC || GET_CODE(table) == ADDR_VEC) { - debug_rtx (insn); - return 2; + int k = GET_CODE(table) == ADDR_DIFF_VEC; + for (int j = 0; j < XVECLEN(table, k); ++j) + { + rtx ref = XVECEXP(table, k, j); + if (!LABEL_REF_NONLOCAL_P(ref)) + { + rtx label = XEXP(ref, 0); + label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + } + } } else { - // -> jump_table_data - rtx table = PATTERN (XEXP(jump_table, 1)); - for (int j = 0; j < XVECLEN(table, 1); ++j) + if (be_very_verbose) { - rtx ref = XVECEXP(table, 1, j); - rtx label = XEXP(ref, 0); - label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + debug_rtx (insn); + debug_rtx (jump_table); } + result = E_JUMP_GOTO_LABEL; + jump_table = 0; + continue; } jump_table = 0; } else { rtx_insn * label = (rtx_insn *) JUMP_LABEL(insn); + if (!label) + { + if (be_very_verbose) + debug_rtx (insn); + result = E_NO_JUMP_LABEL; + continue; + } label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); } - } else if (LABEL_P(insn)) { ii.mark_label (); + jump_table = 0; } else if (CALL_P(insn)) { @@ -1468,7 +1488,7 @@ update_insns () update_insn2index (); update_insn_infos (); - return 0; + return result; } /* convert the lowest set bit into a register number. */ @@ -2953,7 +2973,7 @@ opt_absolute (void) { insn_info & jj = infos[j]; /* TODO: continue also at jump target */ - if (jj.is_jump()) + if (jj.is_jump ()) continue; /* TODO: check if label is visited only from jump targets from herein. then the label is ok. */ if (jj.is_label ()) @@ -3159,60 +3179,59 @@ namespace if (be_very_verbose) log ("ENTER\n"); - for (;;) + unsigned r = update_insns (); + if (!r) { - int done = 1; - int r = update_insns (); - if (r) + for (;;) { - if (be_verbose) - log ("no bbb optimization code %d\n", r); - return 0; - } - if (do_opt_strcpy && opt_strcpy ()) - done = 0, update_insns (); + int done = 1; + if (do_opt_strcpy && opt_strcpy ()) + done = 0, update_insns (); - if (do_commute_add_move && opt_commute_add_move ()) - done = 0, update_insns (); + if (do_commute_add_move && opt_commute_add_move ()) + done = 0, update_insns (); - if (do_propagate_moves && opt_propagate_moves ()) - done = 0, update_insns (); + if (do_propagate_moves && opt_propagate_moves ()) + done = 0, update_insns (); - if (do_const_cmp_to_sub && opt_const_cmp_to_sub ()) - done = 0, update_insns (); + if (do_const_cmp_to_sub && opt_const_cmp_to_sub ()) + done = 0, update_insns (); - if (do_merge_add && opt_merge_add ()) - done = 0; + if (do_merge_add && opt_merge_add ()) + done = 0; - if (do_elim_dead_assign && opt_elim_dead_assign ()) - done = 0, update_insns (); + if (do_elim_dead_assign && opt_elim_dead_assign ()) + done = 0, update_insns (); - if (do_absolute && opt_absolute ()) - done = 0; + if (do_absolute && opt_absolute ()) + done = 0; - if (do_bb_reg_rename) - { - while (opt_reg_rename ()) + if (do_bb_reg_rename) { - update_insns (); - done = 0; + while (opt_reg_rename ()) + { + update_insns (); + done = 0; + } } - } - if (done) - break; - } + if (done) + break; + } - if (do_shrink_stack_frame) - { - if (opt_shrink_stack_frame ()) - update_insns (); + if (do_shrink_stack_frame) + { + if (opt_shrink_stack_frame ()) + update_insns (); + } } + if (r && be_verbose) + log ("no bbb optimization code %d\n", r); if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) dump_insns ("bbb", strchr (string_bbb_opts, 'X')); - return 0; + return r; } } // anon namespace diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 9166b91a69eb..a79b5cddd91b 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -39,6 +39,7 @@ #include "target.h" #include "diagnostic-core.h" #include "langhooks.h" +#include "function.h" #include "config/m68k/amigaos.h" //#define MYDEBUG 1 @@ -50,7 +51,6 @@ //int amiga_declare_object; - #if 0 static int amigaos_put_in_text (tree); static rtx gen_stack_management_call (rtx, rtx, const char *); @@ -436,24 +436,18 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) if (!next_param && TREE_VALUE (param) != void_type_node) cum->num_of_regs = 0; } - - /* check for return values passed in a0 */ - if (cum->num_of_regs) - { - tree type = TYPE_SIZE(TREE_TYPE (DECL_RESULT (current_function_decl))); - int sz = type ? TREE_INT_CST_LOW(type) : 0; - if (sz > 64) /* mark a0 as already used. */ - cum->regs_already_used |= 1 << 8; - } } - //#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM) - // /* If return value is a structure, and we pass the buffer address in a - // register, we can't use this register for our own purposes. - // FIXME: Something similar would be useful for static chain. */ - // if (fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) - // cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM); - //#endif +#if ! defined (PCC_STATIC_STRUCT_RETURN) && defined (M68K_STRUCT_VALUE_REGNUM) + /* If return value is a structure, and we pass the buffer address in a + register, we can't use this register for our own purposes. + FIXME: Something similar would be useful for static chain. */ + if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype)) + cum->regs_already_used |= (1 << M68K_STRUCT_VALUE_REGNUM); +#endif + + if (fntype && DECL_STATIC_CHAIN(fntype)) + cum->regs_already_used |= (1 << STATIC_CHAIN_REGNUM); if (fntype) cum->formal_type = TYPE_ARG_TYPES(fntype); @@ -463,9 +457,8 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) DPRINTF(("1amigaos_init_cumulative_args %p -> %d\r\n", cum, cum->num_of_regs)); } - int -amigaos_function_arg_reg(unsigned regno) +amigaos_function_arg_reg (unsigned regno) { return (mycum.regs_already_used & (1 << regno)) != 0; } @@ -802,20 +795,22 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U #else extern void amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) -{ - if (0 == strncmp(".text", name, 5)) + { + if (0 == strncmp(".text", name, 5)) name = ".text"; - if (0 == strncmp("section ", name, 8)) { + if (0 == strncmp("section ", name, 8)) + { // fprintf (asm_out_file, "\t.section\t%s\n", name); - fprintf (asm_out_file, "\t%s\n", name); - } else { - fprintf (asm_out_file, "\tsection %s\n", name); + fprintf (asm_out_file, "\t%s\n", name); + } + else + { + fprintf (asm_out_file, "\tsection %s\n", name); + } } -} #endif - /* Baserel support. */ /** @@ -846,3 +841,22 @@ read_only_operand (rtx operand) return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P(operand); return 1; } + +rtx +amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED) +{ + if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype)) + return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM); + + return 0; +} + +rtx +amigaos_static_chain_rtx (const_tree fntype, bool incoming ATTRIBUTE_UNUSED) +{ + if (fntype && DECL_STATIC_CHAIN(fntype)) + return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM); + + return 0; +} + diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 284328683c37..c564c3f2db67 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -466,3 +466,14 @@ amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool); && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ ) +#undef TARGET_STRUCT_VALUE_RTX +#define TARGET_STRUCT_VALUE_RTX amigaos_struct_value_rtx +rtx +amigaos_struct_value_rtx(tree fntype, + int incoming ATTRIBUTE_UNUSED); + +#undef TARGET_STATIC_CHAIN +#define TARGET_STATIC_CHAIN amigaos_static_chain_rtx +rtx +amigaos_static_chain_rtx(const_tree fntype, + bool incoming ATTRIBUTE_UNUSED); From bade0e4a363da3d63371623f36c746e976e22a18 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 21 May 2017 07:23:52 +0200 Subject: [PATCH 131/303] @B fix return reg to comply test cases --- gcc/DATESTAMP | 2 +- gcc/config/m68k/m68kamigaos.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3f03e820cb0b..301f35608896 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170520 +20170521 diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index f636e397cfca..a81007bb15d5 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -264,7 +264,10 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ /* put return values in FPU build in FP0 Reg */ #undef FUNCTION_VALUE_REGNO_P #define FUNCTION_VALUE_REGNO_P(N) \ - ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG)) + ((N) == D0_REG || (TARGET_68881 && (N) == FP0_REG)) + +// see 930623-1.c +// ((N) == D0_REG || (N) == A0_REG || (TARGET_68881 && (N) == FP0_REG)) /* Inform the program which CPU we compile for. */ From 3401ac796cd87583972c39b6ab730bf5faead050 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 22 May 2017 20:41:51 +0200 Subject: [PATCH 132/303] @R use a dynamic static_chain register to avoid clashes with asm parameters --- gcc/config/m68k/amigaos.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index a79b5cddd91b..8a92ef99db27 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -447,7 +447,11 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) #endif if (fntype && DECL_STATIC_CHAIN(fntype)) - cum->regs_already_used |= (1 << STATIC_CHAIN_REGNUM); + { + rtx reg = amigaos_static_chain_rtx (decl, 0); + if (reg) + cum->regs_already_used |= (1 << REGNO(reg)); + } if (fntype) cum->formal_type = TYPE_ARG_TYPES(fntype); @@ -852,10 +856,31 @@ amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED) } rtx -amigaos_static_chain_rtx (const_tree fntype, bool incoming ATTRIBUTE_UNUSED) +amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED) { - if (fntype && DECL_STATIC_CHAIN(fntype)) - return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM); + if (!decl || !DECL_STATIC_CHAIN(decl)) + return 0; + + tree fntype = TREE_TYPE(decl); + + unsigned used = 0; + + for (tree formal_type = TYPE_ARG_TYPES(fntype); formal_type; formal_type = TREE_CHAIN(formal_type)) + { + tree asmtree = TYPE_ATTRIBUTES(formal_type); + if (!asmtree || strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) + continue; + + unsigned regno = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low; + used |= 1 << regno; + } + + if (!(used & (1 << 9))) + return gen_rtx_REG (Pmode, 9); + if (!(used & (1 << 10))) + return gen_rtx_REG (Pmode, 10); + if (!(used & (1 << 11))) + return gen_rtx_REG (Pmode, 11); return 0; } From 74d34b98a82894145e0021ed0fc00592210413d7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 23 May 2017 22:22:26 +0200 Subject: [PATCH 133/303] @B fix function flow scanning --- gcc/bbb-opts.c | 95 +++++++++++++++++++++++++++------------------------------- 1 file changed, 44 insertions(+), 51 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 848c18e3be52..a06f1577fb94 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -155,12 +155,15 @@ class insn_info int src_intval; unsigned src_mem_addr; + bool visited; + public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol ( - 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0) + 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited ( + false) { } @@ -408,14 +411,6 @@ class insn_info return proepi; } - inline void - reset () - { - use = 0; - def = 0; - hard = 0; - } - inline void reset_flags () { @@ -574,34 +569,6 @@ class insn_info return *this; } -#if 0 - inline insn_info - operator | (insn_info const & o) const - { - insn_info t; - t.use = use | o.use; - t.def = def | o.def; - t.hard = hard | o.hard; - return t; - } - - inline bool - operator == (insn_info const & o) - { - return use == o.use; - } - - inline insn_info - operator ~ () const - { - insn_info t; - t.use = ~use; - t.def = ~def; - t.hard = ~hard; - return t; - } -#endif - inline insn_info & make_hard () { @@ -628,6 +595,18 @@ class insn_info return true; } + inline bool + visit () const + { + return visited; + } + + inline void + mark_visited () + { + visited = true; + } + void scan (); @@ -959,6 +938,9 @@ typedef std::multimap::iterator l2j_iterator; static std::map insn2index; typedef std::map::iterator i2i_iterator; +static std::set returns; +typedef std::set::iterator su_iterator; + static insn_info * info0; static unsigned usable_regs; @@ -1148,6 +1130,7 @@ clear (void) label2jump.clear (); insn2index.clear (); infos.clear (); + returns.clear (); } /* @@ -1256,11 +1239,14 @@ dump_insns (char const * name, bool all) static void update_insn_infos (void) { - /* own analyze reg life */ + /* add all return (jump outs) and start analysis there. */ std::vector > todo; - todo.push_back (std::make_pair (infos.size () - 1, insn_info ())); + for (su_iterator i = returns.begin (); i != returns.end (); ++i) + todo.push_back (std::make_pair (*i, insn_info ())); + + if (todo.begin () == todo.end ()) + todo.push_back (std::make_pair (infos.size () - 1, insn_info ())); - int pass = 0; while (!todo.empty ()) { std::pair p = *todo.rbegin (); @@ -1270,17 +1256,18 @@ update_insn_infos (void) for (int pos = p.first; pos >= 0; --pos) { - rtx_insn * insn = infos[pos].get_insn (); + insn_info & pp = infos[pos]; + rtx_insn * insn = pp.get_insn (); /* can be NULL as used in opt_shrink_stack_frame(). */ if (!insn) continue; /* no new information -> break. */ - if (pass && infos[pos].contains (ii)) + if (pp.in_proepi () == 0 && pp.visit () && pp.contains (ii)) break; ii.clear_hard_def (); - ii.merge (infos[pos]); + ii.merge (pp); if (LABEL_P(insn)) { @@ -1295,6 +1282,8 @@ update_insn_infos (void) continue; } + pp.mark_visited (); + rtx pattern = PATTERN (insn); insn_info use (insn); use.scan (); @@ -1304,9 +1293,11 @@ update_insn_infos (void) } else if (JUMP_P(insn)) { - if (ANY_RETURN_P(pattern)) + if (pos != p.first) { - ii.reset (); + su_iterator k = returns.find (pos); + if (k != returns.end ()) + break; } } else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER) @@ -1330,10 +1321,9 @@ update_insn_infos (void) use.make_hard (); ii.merge (use); - infos[pos].update (ii); + pp.update (ii); ii.updateWith (use); } - ++pass; } /* fill the mask of general used regs. */ @@ -1389,10 +1379,13 @@ update_insns () if (JUMP_P(insn)) { - inproepilogue = 0; - - if (ANY_RETURN_P(PATTERN (insn))) - continue; + if (inproepilogue || ANY_RETURN_P(PATTERN (insn))) + { + returns.insert (infos.size () - 1); + inproepilogue = 0; + if (ANY_RETURN_P(PATTERN (insn))) + continue; + } ii.mark_jump (); if (jump_table) From b1334e77f8e493eaeb362392f035711d06484be7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 23 May 2017 22:22:44 +0200 Subject: [PATCH 134/303] @B fix static_chain register handling --- gcc/config/m68k/amigaos.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 8a92ef99db27..dc2f2ac74369 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -602,7 +602,6 @@ amigaos_function_arg (cumulative_args_t cum_v, machine_mode mode, const_tree typ void amiga_emit_regparm_clobbers (void) { - rtx sp = gen_raw_REG (Pmode, 15); for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (mycum.regs_already_used & (1 << i)) { @@ -861,19 +860,18 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED) if (!decl || !DECL_STATIC_CHAIN(decl)) return 0; - tree fntype = TREE_TYPE(decl); - unsigned used = 0; + tree fntype = TREE_TYPE(decl); + if (fntype) + for (tree formal_type = TYPE_ARG_TYPES(fntype); formal_type; formal_type = TREE_CHAIN(formal_type)) + { + tree asmtree = TYPE_ATTRIBUTES(TREE_VALUE(formal_type)); + if (!asmtree || strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) + continue; - for (tree formal_type = TYPE_ARG_TYPES(fntype); formal_type; formal_type = TREE_CHAIN(formal_type)) - { - tree asmtree = TYPE_ATTRIBUTES(formal_type); - if (!asmtree || strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(asmtree)))) - continue; - - unsigned regno = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low; - used |= 1 << regno; - } + unsigned regno = TREE_FIXED_CST_PTR(TREE_VALUE(asmtree))->data.low; + used |= 1 << regno; + } if (!(used & (1 << 9))) return gen_rtx_REG (Pmode, 9); @@ -881,6 +879,8 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED) return gen_rtx_REG (Pmode, 10); if (!(used & (1 << 11))) return gen_rtx_REG (Pmode, 11); + if (!(used & (1 << 14))) + return gen_rtx_REG (Pmode, 14); return 0; } From 5b9f0616bb8d5bf7cca7daaa9b5cd4056e0e6f9e Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 24 May 2017 16:27:49 +0200 Subject: [PATCH 135/303] @B fix stack frame shrinking --- gcc/bbb-opts.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 208 insertions(+), 26 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a06f1577fb94..43bcf138fc20 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -157,13 +157,18 @@ class insn_info bool visited; + int sp_offset; + + int dst_autoinc; + int src_autoinc; + public: insn_info (rtx_insn * i = 0, int p = 0) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol ( 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited ( - false) + false), sp_offset (0), dst_autoinc (0), src_autoinc (0) { } @@ -414,6 +419,8 @@ class insn_info inline void reset_flags () { + label = false; + jump = false; compare = false; dst_mem = false; src_mem = false; @@ -435,6 +442,21 @@ class insn_info src_intval = 0; src_mem_addr = 0; + + dst_autoinc = 0; + src_autoinc = 0; + } + + inline int + get_src_autoinc () const + { + return src_autoinc; + } + + inline int + get_dst_autoinc () const + { + return dst_autoinc; } inline bool @@ -595,8 +617,20 @@ class insn_info return true; } + inline int + get_sp_offset () const + { + return sp_offset; + } + + inline void + set_sp_offset (int sp) + { + sp_offset = sp; + } + inline bool - visit () const + is_visited () const { return visited; } @@ -607,6 +641,12 @@ class insn_info visited = true; } + inline void + clear_visited () + { + visited = false; + } + void scan (); @@ -770,6 +810,12 @@ insn_info::fledder (rtx set) { dst_mem = true; rtx mem = XEXP(dst, 0); + + if (GET_CODE(mem) == POST_INC) + dst_autoinc = 1, mem = XEXP(mem, 0); + else if (GET_CODE(mem) == PRE_DEC) + dst_autoinc = -1, mem = XEXP(mem, 0); + if (REG_P(mem)) dst_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) @@ -831,6 +877,12 @@ insn_info::fledder (rtx set) { src_mem = true; rtx mem = XEXP(src, 0); + + if (GET_CODE(mem) == POST_INC) + src_autoinc = 1, mem = XEXP(mem, 0); + else if (GET_CODE(mem) == PRE_DEC) + src_autoinc = -1, mem = XEXP(mem, 0); + if (REG_P(mem)) src_mem_reg = mem; else if (GET_CODE(mem) == CONST_INT) @@ -932,10 +984,15 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr static std::vector infos; typedef std::vector::iterator insn_info_iterator; +// insn->u2.insn_uid -> rtx_insn * static std::multimap label2jump; typedef std::multimap::iterator l2j_iterator; -static std::map insn2index; +// index -> index +static std::multimap jump2label; +typedef std::multimap::iterator j2l_iterator; + +static std::map insn2info; typedef std::map::iterator i2i_iterator; static std::set returns; @@ -948,16 +1005,31 @@ static void update_insn2index () { infos.reserve (infos.size () * 8 / 7 + 2); - insn2index.clear (); + insn2info.clear (); /* needs a separate pass since the insn_infos require fixed addresses for ->get_index() */ for (unsigned i = 0; i < infos.size (); ++i) { insn_info & ii = infos[i]; - insn2index.insert (std::make_pair (ii.get_insn (), &ii)); + insn2info.insert (std::make_pair (ii.get_insn (), &ii)); } info0 = &infos[0]; } +static void +update_label2jump () +{ + for (unsigned index = 0; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + insn2info.insert (std::make_pair (ii.get_insn (), &ii)); + + if (ii.is_label ()) + for (l2j_iterator i = label2jump.find (ii.get_insn ()->u2.insn_uid), k = i; + i != label2jump.end () && i->first == k->first; ++i) + jump2label.insert (std::make_pair (insn2info.find (i->second)->second->get_index (), index)); + } +} + int insn_info::get_index () const { @@ -986,7 +1058,7 @@ insn_info::plus_to_move (rtx_insn * newinsn) insn = newinsn; src_op = (rtx_code) 0; src_reg = XEXP(PATTERN (newinsn), 1); - insn2index.insert (std::make_pair (insn, this)); + insn2info.insert (std::make_pair (insn, this)); // usage flags did not change } @@ -997,8 +1069,8 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii) std::swap (*this, ii); - insn2index.insert (std::make_pair (insn, this)); - insn2index.insert (std::make_pair (ii.insn, &ii)); + insn2info.insert (std::make_pair (insn, this)); + insn2info.insert (std::make_pair (ii.insn, &ii)); // usage flags did not change } @@ -1065,7 +1137,6 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) unsigned offset = addr - base; if (offset <= 0x7ffe) { - rtx olddst = dst; if (base == addr) dst = gen_rtx_MEM (mode, reg); else @@ -1119,7 +1190,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) mark_use (regno); - insn2index.insert (std::make_pair (insn, this)); + insn2info.insert (std::make_pair (insn, this)); } /* * Reset collected data. @@ -1128,7 +1199,8 @@ static void clear (void) { label2jump.clear (); - insn2index.clear (); + jump2label.clear (); + insn2info.clear (); infos.clear (); returns.clear (); } @@ -1160,8 +1232,8 @@ void append_reg_usage (FILE * f, rtx_insn * insn) { - i2i_iterator i = insn2index.find (insn); - if (i == insn2index.end ()) + i2i_iterator i = insn2info.find (insn); + if (i == insn2info.end ()) return; insn_info & ii = *i->second; @@ -1263,7 +1335,7 @@ update_insn_infos (void) continue; /* no new information -> break. */ - if (pp.in_proepi () == 0 && pp.visit () && pp.contains (ii)) + if (pp.in_proepi () == 0 && pp.is_visited () && pp.contains (ii)) break; ii.clear_hard_def (); @@ -1275,8 +1347,8 @@ update_insn_infos (void) for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i; i != label2jump.end () && i->first == k->first; ++i) { - i2i_iterator j = insn2index.find (i->second); - if (j != insn2index.end ()) + i2i_iterator j = insn2info.find (i->second); + if (j != insn2info.end ()) todo.push_back (std::make_pair (j->second->get_index (), ii)); } continue; @@ -1293,11 +1365,14 @@ update_insn_infos (void) } else if (JUMP_P(insn)) { - if (pos != p.first) + if ((unsigned) pos != p.first) { su_iterator k = returns.find (pos); if (k != returns.end ()) - break; + { + pp.clear_visited (); + break; + } } } else if (GET_CODE (pattern) == USE || GET_CODE (pattern) == CLOBBER) @@ -1350,7 +1425,7 @@ update_insn_infos (void) enum AbortCodes { - E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL + E_OK, E_NO_JUMP_LABEL, E_JUMP_TABLE_MISMATCH, E_JUMP_GOTO_LABEL, E_SP_MISMATCH }; /* @@ -1598,8 +1673,8 @@ opt_reg_rename (void) for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i; i != label2jump.end () && i->first == k->first; ++i) { - i2i_iterator j = insn2index.find (i->second); - if (j == insn2index.end ()) + i2i_iterator j = insn2info.find (i->second); + if (j == insn2info.end ()) continue; unsigned start = j->second->get_index (); @@ -1647,8 +1722,8 @@ opt_reg_rename (void) /* follow jump and/or next insn. */ if (JUMP_P(insn)) { - i2i_iterator j = insn2index.find ((rtx_insn *) JUMP_LABEL(insn)); - if (j == insn2index.end ()) + i2i_iterator j = insn2info.find ((rtx_insn *) JUMP_LABEL(insn)); + if (j == insn2info.end ()) { /* whoops - label not found. */ mask = 0; @@ -2488,6 +2563,86 @@ opt_merge_add (void) return change_count; } +/* Update the insn_infos to 'know' the sp offset. */ +static unsigned +track_sp () +{ + // reset visited flags + for (unsigned index = 0; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + ii.clear_visited (); + ii.set_sp_offset (0); + } + + // add entry point + std::vector todo; + todo.push_back (0); + + while (todo.size () > 0) + { + unsigned startpos = todo[todo.size () - 1]; + todo.pop_back (); + + int sp_offset = infos[startpos].get_sp_offset (); + + for (unsigned index = startpos; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + if (ii.in_proepi ()) + continue; + + // already visited? sp_offset must match + if (ii.is_visited ()) + { + if (ii.get_sp_offset () != sp_offset) + return E_SP_MISMATCH; + break; + } + + // mark current insn_info and set sp_offset + ii.mark_visited (); + ii.set_sp_offset (sp_offset); + + // add all referred labels + if (ii.is_jump ()) + { + for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i) + { + insn_info & ll = infos[i->second]; + if (ll.is_visited () && ll.get_sp_offset () != sp_offset) + return E_SP_MISMATCH; + + ll.set_sp_offset (sp_offset); + todo.push_back (i->second); + } + continue; + } + + // is sp modified directly + if (ii.is_dst_reg () && ii.get_dst_regno () == STACK_POINTER_REGNUM) + { + // handle sp = sp + const_int + if (!ii.is_src_reg () || ii.get_src_regno () != STACK_POINTER_REGNUM || ii.get_src_op () != PLUS) + return E_SP_MISMATCH; + + sp_offset = sp_offset + ii.get_src_intval (); + continue; + } + + // handle dst mem autoinc + if (ii.is_dst_mem () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM && ii.get_dst_autoinc ()) + sp_offset += GET_MODE_SIZE(ii.get_mode()) * ii.get_dst_autoinc (); + + // handle src mem autoinc + if (ii.is_src_mem () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM && ii.get_src_autoinc ()) + sp_offset += GET_MODE_SIZE(ii.get_mode()) * ii.get_src_autoinc (); + } + } + + return 0; +} + /** * 1. scan for all used registers. * 2. scan the stack from for omittable push/pop @@ -2517,6 +2672,11 @@ opt_shrink_stack_frame (void) if (!infos.size ()) return 0; + /* needed to track sp correctly. */ + update_label2jump (); + if (track_sp ()) + return 0; // do nothing on stack errors + std::vector a5pos; unsigned pos = 0; @@ -2875,6 +3035,14 @@ opt_shrink_stack_frame (void) rtx pattern = PATTERN (ii.get_insn ()); if (ii.is_compare ()) pattern = XEXP(pattern, 1); + + // lea n(sp),ax + if (ii.get_src_reg() && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS) + { + rtx src = XEXP(pattern, 1); + XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust); + } + if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM) { rtx src = XEXP(pattern, 1); @@ -2902,8 +3070,22 @@ opt_shrink_stack_frame (void) log ("(f) dropping unused frame pointer\n"); for (std::vector::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i) { - SET_INSN_DELETED(infos[*i].get_insn ()); - infos.erase (infos.begin () + *i); + unsigned index = *i; + SET_INSN_DELETED(infos[index].get_insn ()); + while (index > 0 && infos[index].in_proepi () == 2) + --index; + + insn_info & ii = infos[index]; + if (!ii.in_proepi ()) + { + if (ii.get_sp_offset () != 0) + { + log ("(f) adjusting exit sp\n"); + rtx pattern = gen_rtx_SET( + a7, gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset()))); + emit_insn_after (pattern, ii.get_insn ()); + } + } } /* convert all parameter accesses via a5 into a7. */ @@ -3157,7 +3339,7 @@ namespace pass_bbb_optimizations::execute_bbb_optimizations (void) { be_very_verbose = strchr (string_bbb_opts, 'V'); - be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v'); + be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1; bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); From 103cba07eca32f607fa4b9c6cce1ff757c9b97d4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 24 May 2017 16:28:36 +0200 Subject: [PATCH 136/303] @D disable verbose --- gcc/bbb-opts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 43bcf138fc20..9dff55129ae3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3339,7 +3339,7 @@ namespace pass_bbb_optimizations::execute_bbb_optimizations (void) { be_very_verbose = strchr (string_bbb_opts, 'V'); - be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v') || 1; + be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v'); bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); From 3d84b641d630cd99c5ce14eeb42bc5307be3ffa8 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 24 May 2017 16:30:36 +0200 Subject: [PATCH 137/303] @V bump date --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 301f35608896..8afbbd33cdaa 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170521 +20170524 From a2ab0f8a257f6900e89d574ab8adf366fbd3d4a7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 24 May 2017 20:06:02 +0200 Subject: [PATCH 138/303] @B fix shrink stack frame - do not modify sp offsets in prologue/epilogue --- gcc/bbb-opts.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9dff55129ae3..bbbf02561fb4 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1239,13 +1239,14 @@ append_reg_usage (FILE * f, rtx_insn * insn) insn_info & ii = *i->second; if (f != stderr) - fprintf (f, "\n\t\t\t\t\t\t|%c ", ii.is_stack () ? 's' : ' '); + fprintf (f, "\n\t\t\t\t\t\t|%c ", + ii.is_stack () ? 's' : ii.in_proepi () == 1 ? 'p' : ii.in_proepi () == 2 ? 'e' : ' '); for (int j = 0; j < 8; ++j) if (ii.is_use (j) || ii.is_def (j)) { fprintf (f, ii.is_hard (j) ? "!" : " "); - fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (j) ? "." : " "); fprintf (f, "d%d ", j); } else @@ -1255,7 +1256,7 @@ append_reg_usage (FILE * f, rtx_insn * insn) if (ii.is_use (j) || ii.is_def (j)) { fprintf (f, ii.is_hard (j) ? "!" : " "); - fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (j) ? "." : " "); fprintf (f, "a%d ", j - 8); } else @@ -3032,12 +3033,15 @@ opt_shrink_stack_frame (void) for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; + if (ii.in_proepi ()) + continue; + rtx pattern = PATTERN (ii.get_insn ()); if (ii.is_compare ()) pattern = XEXP(pattern, 1); // lea n(sp),ax - if (ii.get_src_reg() && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS) + if (ii.get_src_reg () && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS) { rtx src = XEXP(pattern, 1); XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust); @@ -3049,13 +3053,13 @@ opt_shrink_stack_frame (void) rtx plus = XEXP(src, 0); if (ii.get_src_op ()) plus = XEXP(plus, 0); - XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_src_mem_addr () - adjust); + XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_src_mem_addr () - adjust); } if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM) { rtx plus = XEXP(XEXP(pattern, 0), 0); - XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, ii.get_dst_intval () - adjust); + XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_dst_intval () - adjust); } } } From 948b24860fbecf6442f8d9dca3b932a951df57b1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 26 May 2017 12:53:30 +0200 Subject: [PATCH 139/303] @B fix inserting exit sp correction, @B fix parallel pop if stack frame gets removed, @B fix patch only sp offsets referring to local vars/params --- gcc/DATESTAMP | 2 +- gcc/bbb-opts.c | 139 ++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 103 insertions(+), 38 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 8afbbd33cdaa..4d8890e894e9 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170524 +20170526 diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index bbbf02561fb4..b716cf24a9a0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -111,6 +111,11 @@ log (char const * fmt, ...) return retval; } +enum proepis +{ + IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP +}; + /* Information for each insn to detect alive registers. Enough for m68k. * Why a class? Maybe extend it for general usage. * @@ -126,7 +131,7 @@ class insn_info unsigned use; // bit set if registers are used in program flow unsigned def; // bit set if registers are defined here - int proepi; // 1 = in prologue, 2 = in epilogue, 0 = other + enum proepis proepi; bool stack; // part of stack frame insns @@ -163,7 +168,7 @@ class insn_info int src_autoinc; public: - insn_info (rtx_insn * i = 0, int p = 0) : + insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol ( @@ -416,6 +421,12 @@ class insn_info return proepi; } + inline void + set_proepi (enum proepis p) + { + proepi = p; + } + inline void reset_flags () { @@ -784,6 +795,9 @@ insn_info::scan_rtx (rtx x) void insn_info::fledder (rtx set) { + if (GET_CODE(set) == PARALLEL) + return; + rtx dst = SET_DEST(set); rtx src = SET_SRC(set); @@ -1239,8 +1253,10 @@ append_reg_usage (FILE * f, rtx_insn * insn) insn_info & ii = *i->second; if (f != stderr) - fprintf (f, "\n\t\t\t\t\t\t|%c ", - ii.is_stack () ? 's' : ii.in_proepi () == 1 ? 'p' : ii.in_proepi () == 2 ? 'e' : ' '); + fprintf (f, "\n\t\t\t\t\t\t|"); + + fprintf (f, "%c ", + ii.is_stack () ? 's' : ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' '); for (int j = 0; j < 8; ++j) if (ii.is_use (j) || ii.is_def (j)) @@ -1336,7 +1352,7 @@ update_insn_infos (void) continue; /* no new information -> break. */ - if (pp.in_proepi () == 0 && pp.is_visited () && pp.contains (ii)) + if (pp.in_proepi () == IN_CODE && pp.is_visited () && pp.contains (ii)) break; ii.clear_hard_def (); @@ -1393,7 +1409,7 @@ update_insn_infos (void) } /* mark not renameable in prologue/epilogue. */ - if (infos[pos].in_proepi ()) + if (infos[pos].in_proepi () != IN_CODE) use.make_hard (); ii.merge (use); @@ -1407,7 +1423,7 @@ update_insn_infos (void) for (unsigned i = 0; i < infos.size (); ++i) { insn_info & ii = infos[i]; - if (ii.in_proepi () != 1) + if (ii.in_proepi () != IN_PROLOGUE) break; zz.or_use (ii); @@ -1441,7 +1457,7 @@ update_insns () clear (); - char inproepilogue = 1; + enum proepis inproepilogue = IN_PROLOGUE; /* create a vector with relevant insn. */ for (insn = get_insns (); insn; insn = next) { @@ -1458,7 +1474,7 @@ update_insns () if (inproepilogue || ANY_RETURN_P(PATTERN (insn))) { returns.insert (infos.size () - 1); - inproepilogue = 0; + inproepilogue = IN_CODE; if (ANY_RETURN_P(PATTERN (insn))) continue; } @@ -1548,9 +1564,9 @@ update_insns () else if (NOTE_P(insn)) { if (NOTE_KIND(insn) == NOTE_INSN_PROLOGUE_END) - inproepilogue = 0; + inproepilogue = IN_CODE; else if (NOTE_KIND(insn) == NOTE_INSN_EPILOGUE_BEG) - inproepilogue = 2; + inproepilogue = IN_EPILOGUE; } } @@ -2590,7 +2606,7 @@ track_sp () for (unsigned index = startpos; index < infos.size (); ++index) { insn_info & ii = infos[index]; - if (ii.in_proepi ()) + if (ii.in_proepi () != IN_CODE) continue; // already visited? sp_offset must match @@ -2624,7 +2640,7 @@ track_sp () if (ii.is_dst_reg () && ii.get_dst_regno () == STACK_POINTER_REGNUM) { // handle sp = sp + const_int - if (!ii.is_src_reg () || ii.get_src_regno () != STACK_POINTER_REGNUM || ii.get_src_op () != PLUS) + if (!ii.get_src_reg () || ii.get_src_regno () != STACK_POINTER_REGNUM || ii.get_src_op () != PLUS) return E_SP_MISMATCH; sp_offset = sp_offset + ii.get_src_intval (); @@ -2698,7 +2714,7 @@ opt_shrink_stack_frame (void) insn_info & ii = infos[pos]; insn = ii.get_insn (); - if (ii.in_proepi () != 1) + if (ii.in_proepi () != IN_PROLOGUE) break; rtx pattern = PATTERN (insn); @@ -2770,7 +2786,7 @@ opt_shrink_stack_frame (void) { while (pos < infos.size ()) { - if (infos[pos].in_proepi ()) + if (infos[pos].in_proepi () != IN_CODE) break; ++pos; } @@ -2780,7 +2796,7 @@ opt_shrink_stack_frame (void) { insn_info & ii = infos[pos]; insn = ii.get_insn (); - if (JUMP_P(insn) || LABEL_P(insn) || !ii.in_proepi ()) + if (JUMP_P(insn) || LABEL_P(insn) || ii.in_proepi () == IN_CODE) break; /* omit the frame pointer a5. */ @@ -2831,7 +2847,7 @@ opt_shrink_stack_frame (void) for (unsigned i = 0; i < infos.size (); ++i) { insn_info & jj = infos[i]; - if (jj.in_proepi ()) + if (jj.in_proepi () == IN_CODE) continue; ii.or_use (jj); @@ -2843,6 +2859,8 @@ opt_shrink_stack_frame (void) unsigned changed = 0; unsigned adjust = 0; + unsigned regs_seen = 0; + unsigned regs_total_size = 0; /* now all push/pop insns are in temp. */ for (unsigned i = 0; i < infos.size (); ++i) { @@ -2861,6 +2879,11 @@ opt_shrink_stack_frame (void) if (REG_P(dst) && REGNO(dst) == FRAME_POINTER_REGNUM) continue; + if (ii.in_proepi () == IN_EPILOGUE) + ii.set_proepi (IN_EPILOGUE_PARALLEL_POP); + + regs_seen = 0; + regs_total_size = 0; std::vector regs; std::vector clobbers; for (int j = 0; j < XVECLEN(pattern, 0); ++j) @@ -2884,15 +2907,20 @@ opt_shrink_stack_frame (void) if (i < prologueend) paramstart += 4; unsigned regbit = 1 << REGNO(reg); + + ++regs_seen; if (freemask & regbit) { log (i < prologueend ? "(f) remove push for %s\n" : "(f) remove pop for %s\n", reg_names[REGNO(reg)]); if (i < prologueend) - adjust += 4; + adjust += GET_MODE_SIZE(GET_MODE(reg)); } else - regs.push_back (copy_reg (reg, -1)); + { + regs_total_size += GET_MODE_SIZE(GET_MODE(reg)); + regs.push_back (copy_reg (reg, -1)); + } } /* add room for add. @@ -2901,10 +2929,9 @@ opt_shrink_stack_frame (void) * Otherwise a7 is used and with (a7)+ addressing. */ int add1 = i < prologueend || !usea5 ? 1 : 0; - if ((int) regs.size () + add1 + (int) clobbers.size () < XVECLEN(pattern, 0) || regs.size () <= 2) + if (regs.size () < regs_seen) { - log ("(f) shrinking stack frame from %d to %d\n", XVECLEN(pattern, 0) - add1 - clobbers.size (), - regs.size ()); + log ("(f) shrinking stack frame from %d to %d\n", regs_seen, regs.size ()); if (regs.size () <= 2) { changed = 1; @@ -3033,7 +3060,7 @@ opt_shrink_stack_frame (void) for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; - if (ii.in_proepi ()) + if (ii.in_proepi () != IN_CODE) continue; rtx pattern = PATTERN (ii.get_insn ()); @@ -3043,11 +3070,14 @@ opt_shrink_stack_frame (void) // lea n(sp),ax if (ii.get_src_reg () && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS) { - rtx src = XEXP(pattern, 1); - XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust); + // touch only if above pushed parameters + if (ii.get_src_intval () > -ii.get_sp_offset ()) + { + rtx src = XEXP(pattern, 1); + XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust); + } } - - if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM) + else if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM) { rtx src = XEXP(pattern, 1); rtx plus = XEXP(src, 0); @@ -3076,19 +3106,18 @@ opt_shrink_stack_frame (void) { unsigned index = *i; SET_INSN_DELETED(infos[index].get_insn ()); - while (index > 0 && infos[index].in_proepi () == 2) + + // move to last insn in epilogue + while (index - 1 > 0 && infos[index - 1].in_proepi () >= IN_EPILOGUE) --index; insn_info & ii = infos[index]; - if (!ii.in_proepi ()) + if (ii.get_sp_offset () != 0) { - if (ii.get_sp_offset () != 0) - { - log ("(f) adjusting exit sp\n"); - rtx pattern = gen_rtx_SET( - a7, gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset()))); - emit_insn_after (pattern, ii.get_insn ()); - } + log ("(f) adjusting exit sp\n"); + rtx pattern = gen_rtx_SET(a7, + gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset()))); + emit_insn_before (pattern, ii.get_insn ()); } } @@ -3097,7 +3126,43 @@ opt_shrink_stack_frame (void) { insn_info & ii = infos[i]; if (ii.get_myuse () & (1 << FRAME_POINTER_REGNUM)) - ii.a5_to_a7 (a7); + { + ii.a5_to_a7 (a7); + if (regs_seen && ii.in_proepi () == IN_EPILOGUE_PARALLEL_POP) + { + // exit sp insn needs an + + rtx pattern = PATTERN (ii.get_insn ()); + unsigned sz = XVECLEN(pattern, 0); + + rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (sz + 1)); + unsigned n = 0; + for (unsigned j = 0; j < sz; ++j) + { + rtx set = XVECEXP(pattern, 0, j); + rtx reg = SET_DEST(set); + rtx mem = SET_SRC(set); + rtx plus = XEXP(mem, 0); + if (n) + { + XEXP(plus, 1) = gen_rtx_CONST_INT (SImode, n); + } + else + { + XEXP(mem, 0) = XEXP(plus, 0); + } + n += GET_MODE_SIZE(GET_MODE(reg)); + XVECEXP(parallel, 0, j + 1) = set; + } + + rtx a = copy_reg (a7, -1); + a->frame_related = 1; + rtx plus = gen_rtx_PLUS(SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size)); + rtx set = gen_rtx_SET(a, plus); + XVECEXP(parallel, 0, 0) = set; + SET_INSN_DELETED(ii.get_insn ()); + ii.set_insn (emit_insn_after (parallel, ii.get_insn ())); + } + } ii.unset (FRAME_POINTER_REGNUM); } From 0c94ad510c11dbd020d66482ac4ef28857f86d2e Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 26 May 2017 21:20:04 +0200 Subject: [PATCH 140/303] @B fix flow recog loop --- gcc/bbb-opts.c | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index b716cf24a9a0..6b1a6bb5f3c0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -177,6 +177,12 @@ class insn_info { } + inline ptrdiff_t + operator < (insn_info const & o) const + { + return this - &o; + } + int get_index () const; @@ -1329,21 +1335,20 @@ static void update_insn_infos (void) { /* add all return (jump outs) and start analysis there. */ - std::vector > todo; + std::set todo; for (su_iterator i = returns.begin (); i != returns.end (); ++i) - todo.push_back (std::make_pair (*i, insn_info ())); + todo.insert (*i); if (todo.begin () == todo.end ()) - todo.push_back (std::make_pair (infos.size () - 1, insn_info ())); + todo.insert (infos.size () - 1); while (!todo.empty ()) { - std::pair p = *todo.rbegin (); - todo.pop_back (); + int start = *todo.begin (); + todo.erase (todo.begin ()); + insn_info ii = infos[start]; - insn_info ii = p.second; - - for (int pos = p.first; pos >= 0; --pos) + for (int pos = start; pos >= 0; --pos) { insn_info & pp = infos[pos]; rtx_insn * insn = pp.get_insn (); @@ -1352,7 +1357,7 @@ update_insn_infos (void) continue; /* no new information -> break. */ - if (pp.in_proepi () == IN_CODE && pp.is_visited () && pp.contains (ii)) + if (pos != start && pp.is_visited () && !JUMP_P(insn) && pp.contains (ii)) break; ii.clear_hard_def (); @@ -1366,8 +1371,20 @@ update_insn_infos (void) { i2i_iterator j = insn2info.find (i->second); if (j != insn2info.end ()) - todo.push_back (std::make_pair (j->second->get_index (), ii)); + { + unsigned index = j->second->get_index (); + insn_info & jj = infos[index]; + if (!jj.is_visited () || !jj.contains (ii)) + { + jj.updateWith (ii); + todo.insert (index); + } + } } + + if (pos == start) + pp.mark_visited (); +// pp.update (ii); continue; } @@ -1382,7 +1399,7 @@ update_insn_infos (void) } else if (JUMP_P(insn)) { - if ((unsigned) pos != p.first) + if (pos != start) { su_iterator k = returns.find (pos); if (k != returns.end ()) @@ -2607,7 +2624,10 @@ track_sp () { insn_info & ii = infos[index]; if (ii.in_proepi () != IN_CODE) - continue; + { + ii.set_sp_offset (sp_offset); + continue; + } // already visited? sp_offset must match if (ii.is_visited ()) @@ -2847,7 +2867,7 @@ opt_shrink_stack_frame (void) for (unsigned i = 0; i < infos.size (); ++i) { insn_info & jj = infos[i]; - if (jj.in_proepi () == IN_CODE) + if (jj.in_proepi () != IN_CODE) continue; ii.or_use (jj); @@ -3104,7 +3124,7 @@ opt_shrink_stack_frame (void) log ("(f) dropping unused frame pointer\n"); for (std::vector::reverse_iterator i = a5pos.rbegin (); i != a5pos.rend (); ++i) { - unsigned index = *i; + int index = *i; SET_INSN_DELETED(infos[index].get_insn ()); // move to last insn in epilogue @@ -3112,7 +3132,7 @@ opt_shrink_stack_frame (void) --index; insn_info & ii = infos[index]; - if (ii.get_sp_offset () != 0) + if (ii.in_proepi () >= IN_EPILOGUE && ii.get_sp_offset () != 0) { log ("(f) adjusting exit sp\n"); rtx pattern = gen_rtx_SET(a7, From aea30fb817d7af78317be6f363975ef30a56129b Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 27 May 2017 00:33:52 +0200 Subject: [PATCH 141/303] @R disabled soft float in gcc --- .project | 7 +++++++ .settings/language.settings.xml | 2 +- libgcc/config.host | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.project b/.project index 22b8c5a11f48..500c9ee08dca 100644 --- .project +++ .project @@ -24,4 +24,11 @@ org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + build-gcc + 2 + D:/develop/workspaces/c1/amigaos-cross-toolchain/.build-m68k/build/gcc-6 + + diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index c6ac9211311a..caef162d88d1 100755 --- .settings/language.settings.xml +++ .settings/language.settings.xml @@ -16,7 +16,7 @@ - + diff --git a/libgcc/config.host b/libgcc/config.host index 2eb982df6274..f456ff689ad9 100644 --- libgcc/config.host +++ libgcc/config.host @@ -817,7 +817,8 @@ m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; m68k-*-amiga*) - tmake_file="$tmake_file m68k/t-floatlib" + tmake_file="$tmake_file +# m68k/t-floatlib" ;; m68k-*-elf* | fido-*-elf) tmake_file="$tmake_file m68k/t-floatlib" From 22166a8c54eedddc7f3bb718c3be733dae48d367 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 27 May 2017 13:35:18 +0100 Subject: [PATCH 142/303] @V bump datestamp --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4d8890e894e9..3042ace073af 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170526 +20170527-133518 From bdc1872397c7c616974499050001710681d3346e Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 27 May 2017 13:50:12 +0100 Subject: [PATCH 143/303] @V bump datestamp --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3042ace073af..cb171356c5e5 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170527-133518 +20170527-135012 From 497b371bb123e18aa03089ff176b991be46a4324 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 27 May 2017 15:14:21 +0100 Subject: [PATCH 144/303] @V bump datestamp --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index cb171356c5e5..3ebdd3995a41 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170527-135012 +20170527-151421 From 40c89d195204d51e61d08bdd7f0d10b5f1b64db7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 27 May 2017 23:28:12 +0200 Subject: [PATCH 145/303] @R fixes for TARGET_AMIGAOS_VASM --- gcc/config/m68k/m68k.c | 13 +++++++++ gcc/config/m68k/m68kamigaos.h | 61 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 3b51b2541bc9..d123cc065c18 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -4593,20 +4593,33 @@ print_operand (FILE *file, rtx op, int letter) { long l; REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), l); +#ifndef TARGET_AMIGAOS_VASM asm_fprintf (file, "%I0x%lx", l & 0xFFFFFFFF); +#else + asm_fprintf (file, "%I$%lx", l & 0xFFFFFFFF); +#endif } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode) { long l[3]; REAL_VALUE_TO_TARGET_LONG_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l); +#ifndef TARGET_AMIGAOS_VASM asm_fprintf (file, "%I0x%lx%08lx%08lx", l[0] & 0xFFFFFFFF, l[1] & 0xFFFFFFFF, l[2] & 0xFFFFFFFF); +#else + asm_fprintf (file, "%I$%lx%08lx%08lx", l[0] & 0xFFFFFFFF, + l[1] & 0xFFFFFFFF, l[2] & 0xFFFFFFFF); +#endif } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode) { long l[2]; REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l); +#ifndef TARGET_AMIGAOS_VASM asm_fprintf (file, "%I0x%lx%08lx", l[0] & 0xFFFFFFFF, l[1] & 0xFFFFFFFF); +#else + asm_fprintf (file, "%I$%lx%08lx", l[0] & 0xFFFFFFFF, l[1] & 0xFFFFFFFF); +#endif } else { diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index a81007bb15d5..aabd0ab5e521 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -31,6 +31,17 @@ along with GCC; see the file COPYING3. If not see #define SWBEG_ASM_OP "\t.swbeg\t" #endif +#ifdef TARGET_AMIGAOS_VASM +#undef ASM_STABS_OP +#define ASM_STABS_OP "|\t.stabs\t" + +#undef ASM_STABD_OP +#define ASM_STABD_OP "|\t.stabd\t" + +#undef ASM_STABN_OP +#define ASM_STABN_OP "|\t.stabn\t" +#endif + #undef PIC_REG #define PIC_REG 12 @@ -410,11 +421,16 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ ")" #undef STARTFILE_SPEC +#ifdef TARGET_AMIGAOS_VASM +#define STARTFILE_SPEC \ + "startup%O%s" +#else #define STARTFILE_SPEC \ "%{noixemul:%(startfile_libnix)} " \ "%{mcrt=nix*:%(startfile_libnix)} " \ "%{mcrt=ixemul:%(startfile_ixemul)} " \ "%{mcrt=clib2:%(startfile_clib2)}" +#endif #define ENDFILE_IXEMUL_SPEC "" #define ENDFILE_LIBNIX_SPEC "-lstubs" @@ -456,11 +472,16 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{mstackcheck:-lstack} " \ "%{mstackextend:-lstack}" +#ifdef TARGET_AMIGAOS_VASM +#define LIB_SPEC \ + "-lvc -lamiga " +#else #define LIB_SPEC \ "%{noixemul:%(lib_libnix)} " \ "%{mcrt=nix*:%(lib_libnix)} " \ "%{mcrt=ixemul:%(lib_ixemul)} " \ "%{mcrt=clib2:%(lib_clib2)}" +#endif #define LIBGCC_IXEMUL_SPEC "" #define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \ @@ -487,7 +508,26 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ Also, pass appropriate linker flavours depending on user-supplied commandline options. */ +#ifdef TARGET_AMIGAOS_VASM #define LINK_SPEC \ + "%{noixemul:%(link_libnix)} " \ + "%{mcrt=nix*:%(link_libnix)} " \ + "%{mcrt=ixemul:%(link_ixemul)} " \ + "%{mcrt=clib2:%(link_clib2)} " \ + "%{fbaserel:%{!resident:-m amiga_bss -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \ + "%{resident:-m amiga_bss -amiga-datadata-reloc -fl libb %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \ + "%{fbaserel32:%{!resident32:-m amiga_bss -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}}} " \ + "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \ + "%{mcpu=68020:-fl libm020} " \ + "%{m68020:-fl libm020} " \ + "%{mc68020:-fl libm020} " \ + "%{m68030:-fl libm020} " \ + "%{m68040:-fl libm020} " \ + "%{m68060:-fl libm020} " \ + "%{m68020-40:-fl libm020} " \ + "%{m68020-60:-fl libm020} " \ + "%{m68881:-fl libm881}" +#else "%{noixemul:%(link_libnix)} " \ "%{mcrt=nix*:%(link_libnix)} " \ "%{mcrt=ixemul:%(link_ixemul)} " \ @@ -506,6 +546,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{m68020-40:-fl libm020} " \ "%{m68020-60:-fl libm020} " \ "%{m68881:-fl libm881}" +#endif /* Translate '-resident' to '-fbaserel' (they differ in linking stage only). Don't put function addresses in registers for PC-relative code. */ @@ -524,6 +565,23 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ at the end of command line. Otherwise linker chooses generic functions from libgcc.a instead AmigaOS-specific counterparts from libnix.a. */ +#ifdef TARGET_AMIGAOS_VASM +#define LINK_COMMAND_SPEC \ + "%{!fsyntax-only:" \ + "%{!c:" \ + "%{!M:" \ + "%{!MM:" \ + "%{!E:" \ + "%{!S:" \ + "%(linker) -Cvbcc %l %X %{o*} %{A} %{d} %{e*} %{m} " \ + "%{N} %{n} %{r} %{s} %{t} %{u*} %{x} %{z} %{Z} " \ + "%{!A:%{!nostdlib:%{!nostartfiles:%S}}} " \ + "%{static:} %{L*} %D %o " \ + "%{!nostdlib:%{!nodefaultlibs:%L}} " \ + "%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \ + "%{!nostdlib:%{!nodefaultlibs:%G}} " \ + "%{T*} }}}}}} " +#else #define LINK_COMMAND_SPEC \ "%{!fsyntax-only:" \ "%{!c:" \ @@ -538,7 +596,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{!nostdlib:%{!nodefaultlibs:%L}} " \ "%{!A:%{!nostdlib:%{!nostartfiles:%E}}} " \ "%{!nostdlib:%{!nodefaultlibs:%G}} " \ - "%{T*} }}}}}} " \ + "%{T*} }}}}}} " +#endif extern const char * amiga_m68k_prefix_func(int, const char **); From f86473acc971c74d399d0b0f7de418ab45a9cd46 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 28 May 2017 07:12:48 +0200 Subject: [PATCH 146/303] @B fix defines --- gcc/config/m68k/m68kamigaos.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index aabd0ab5e521..a286fff9c688 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -528,6 +528,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{m68020-60:-fl libm020} " \ "%{m68881:-fl libm881}" #else +#define LINK_SPEC \ "%{noixemul:%(link_libnix)} " \ "%{mcrt=nix*:%(link_libnix)} " \ "%{mcrt=ixemul:%(link_ixemul)} " \ From 205a71781ce9bd12d9360462dfcb7e87bacc382b Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 28 May 2017 06:24:32 +0100 Subject: [PATCH 147/303] @V bump datestamp --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3ebdd3995a41..12703d9cab62 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170527-151421 +20170528-062432 From 208ca25348e2fe8597be046ba1e841e5cddb5448 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 28 May 2017 20:39:12 +0200 Subject: [PATCH 148/303] @I use set instead of vector to track the stack pointer --- gcc/bbb-opts.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 6b1a6bb5f3c0..db1d1b6b369e 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2610,13 +2610,13 @@ track_sp () } // add entry point - std::vector todo; - todo.push_back (0); + std::set todo; + todo.insert (0); - while (todo.size () > 0) + while (todo.begin () != todo.end ()) { - unsigned startpos = todo[todo.size () - 1]; - todo.pop_back (); + unsigned startpos = *todo.begin (); + todo.erase (todo.begin ()); int sp_offset = infos[startpos].get_sp_offset (); @@ -2651,7 +2651,7 @@ track_sp () return E_SP_MISMATCH; ll.set_sp_offset (sp_offset); - todo.push_back (i->second); + todo.insert (i->second); } continue; } From 8f616d112701133d7bafb8db6dceb6895eead852 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 29 May 2017 11:31:30 +0200 Subject: [PATCH 149/303] @I improved reg usage tracking and reg renaming --- gcc/bbb-opts.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index db1d1b6b369e..0b71eef7d5c0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -677,15 +677,19 @@ class insn_info if (def & hard) return 0; - if (!def || (def & ~(1 << FIRST_PSEUDO_REGISTER)) > 0x1000) + if (!def) return 0; - unsigned mask = def - 1; + unsigned def_no_cc = def & ~(1 << FIRST_PSEUDO_REGISTER); + if (def_no_cc > 0x4000) + return 0; + + unsigned mask = def_no_cc - 1; /* more than one register -> don't touch. */ if ((mask & ~def) != mask) return 0; - if (def > 0xff) + if (def_no_cc > 0xff) mask &= 0xff00; return mask & ~use; @@ -1384,7 +1388,17 @@ update_insn_infos (void) if (pos == start) pp.mark_visited (); -// pp.update (ii); + + /* check previous insn for jump */ + if (pos > 0 && infos[pos - 1].is_jump ()) + { + rtx_insn * prev = infos[pos - 1].get_insn (); + rtx set = single_set (prev); + /* unconditional? -> break! */ + if (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE) + break; + } + continue; } @@ -1492,7 +1506,9 @@ update_insns () { returns.insert (infos.size () - 1); inproepilogue = IN_CODE; - if (ANY_RETURN_P(PATTERN (insn))) + rtx set = single_set (insn); + if (ANY_RETURN_P(PATTERN (insn)) + || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE)) continue; } @@ -1556,6 +1572,7 @@ update_insns () { ii.mark_label (); jump_table = 0; + ii.set_proepi(inproepilogue = IN_CODE); } else if (CALL_P(insn)) { @@ -1677,17 +1694,17 @@ opt_reg_rename (void) continue; /* first = pos to start, second indicates to treat def as use. */ - std::vector todo; + std::set todo; std::set found; if (index + 1 < infos.size ()) - todo.push_back (index + 1); + todo.insert (index + 1); found.insert (index); /* a register was defined, follow all branches. */ - while (mask && todo.size ()) + while (mask && todo.begin () != todo.end ()) { - unsigned runpos = todo[todo.size () - 1]; - todo.pop_back (); + unsigned runpos = *todo.begin (); + todo.erase (todo.begin ()); for (unsigned pos = runpos; mask && pos < infos.size (); ++pos) { @@ -1716,7 +1733,7 @@ opt_reg_rename (void) continue; start = find_start (found, start, rename_regno); - todo.push_back (start); + todo.insert (start); } continue; } @@ -1774,9 +1791,9 @@ opt_reg_rename (void) if (bb.is_use (rename_regno)) { unsigned start = find_start (found, label_index, rename_regno); - todo.push_back (start); + todo.insert (start); } - todo.push_back (label_index + 1); + todo.insert (label_index + 1); } rtx jmppattern = PATTERN (insn); if (GET_CODE(jmppattern) == PARALLEL) From 19cecc88e679fc1926df66fc4df5feaaaa4fce63 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 29 May 2017 20:25:44 +0200 Subject: [PATCH 150/303] @B #25 cpu defaults now to m68000 (was m68040) --- gcc/config/m68k/m68kamigaos.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index a286fff9c688..8a25f8cbfdfb 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -367,7 +367,8 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #endif #undef ASM_CPU_SPEC -#define ASM_CPU_SPEC \ +#define ASM_CPU_SPEC \ + "%{mcpu=*:-m%*} " \ "%{m68000|mc68000:-m68010} " \ "%{m6802*|mc68020:-m68020} " \ "%{m68030} " \ @@ -376,7 +377,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #ifndef TARGET_AMIGAOS_VASM #define ASM_CPU_DEFAULT_SPEC \ - "%{!m680*:%{!mc680*:-m68040}}" + "%{!m680*:%{!mc680*:%{!mcpu=*:-m68000}}}" #else #define ASM_CPU_DEFAULT_SPEC \ "%{!m680*:%{!mc680*:-m68000}}" From f6cdedb91a27adc4aa437490c846d0863550b011 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 29 May 2017 20:27:07 +0200 Subject: [PATCH 151/303] @B fix handling parallel insns with set + clobber --- gcc/bbb-opts.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 0b71eef7d5c0..a76b70385d9c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -805,7 +805,7 @@ insn_info::scan_rtx (rtx x) void insn_info::fledder (rtx set) { - if (GET_CODE(set) == PARALLEL) + if (!set || GET_CODE(set) == PARALLEL) return; rtx dst = SET_DEST(set); @@ -1142,13 +1142,13 @@ insn_info::set_insn (rtx_insn * newinsn) reset_flags (); - fledder (PATTERN (insn)); + fledder (single_set (insn)); } void insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) { - rtx set = PATTERN (get_insn ()); + rtx set = single_set (get_insn ()); rtx src = SET_SRC(set); rtx dst = SET_DEST(set); @@ -1572,7 +1572,7 @@ update_insns () { ii.mark_label (); jump_table = 0; - ii.set_proepi(inproepilogue = IN_CODE); + ii.set_proepi (inproepilogue = IN_CODE); } else if (CALL_P(insn)) { @@ -3100,7 +3100,7 @@ opt_shrink_stack_frame (void) if (ii.in_proepi () != IN_CODE) continue; - rtx pattern = PATTERN (ii.get_insn ()); + rtx pattern = single_set (ii.get_insn ()); if (ii.is_compare ()) pattern = XEXP(pattern, 1); From 5ab0b26c5f50357a306188c7348c818136106b19 Mon Sep 17 00:00:00 2001 From: fautomat Date: Mon, 29 May 2017 21:58:32 +0100 Subject: [PATCH 152/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4d8890e894e9..b5d1e40685b6 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170526 +20170529-215512 From fb1df368db776fcc6091421a2b538b346ffccad0 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 30 May 2017 19:03:36 +0200 Subject: [PATCH 153/303] @B jumps inside epilogue which result from chained calls are still CALL insns... --- gcc/bbb-opts.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a76b70385d9c..a187666945f0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1408,10 +1408,7 @@ update_insn_infos (void) insn_info use (insn); use.scan (); - if (CALL_P(insn)) - { - } - else if (JUMP_P(insn)) + if (CALL_P(insn) || JUMP_P(insn)) { if (pos != start) { @@ -1577,6 +1574,11 @@ update_insns () else if (CALL_P(insn)) { ii.mark_call (); + if (inproepilogue) + { + returns.insert (infos.size () - 1); + inproepilogue = IN_CODE; + } } else { From c11163ef6d4388e710fde92c1cc609ac06b0a5fc Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 30 May 2017 23:12:51 +0200 Subject: [PATCH 154/303] @B fix single reg pop if stack frame gets removed --- gcc/bbb-opts.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a187666945f0..a2c305c1f65c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1132,6 +1132,15 @@ replace_reg (rtx x, unsigned regno, rtx newreg, int offset) void insn_info::a5_to_a7 (rtx a7) { + if (proepi == IN_EPILOGUE && src_mem_reg && get_src_mem_regno () == FRAME_POINTER_REGNUM) + { + rtx set = single_set (insn); + if (set) + { + SET_SRC(set) = gen_rtx_MEM(mode, gen_rtx_POST_INC(SImode, a7)); + return; + } + } replace_reg (PATTERN (insn), FRAME_POINTER_REGNUM, a7, -4); } From 1ebf051b5bd078fc19f105904090ffc1743752fc Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 1 Jun 2017 16:05:59 +0200 Subject: [PATCH 155/303] @B improved scan to treat endless loops (.L1: jra L1) and similar constructs --- gcc/bbb-opts.c | 60 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a2c305c1f65c..26ca56bbb84d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -483,12 +483,18 @@ class insn_info } inline void - mark_use (int regno) + mark_myuse (int regno) { myuse |= 1 << regno; use |= 1 << regno; } + inline void + mark_use (int regno) + { + use |= 1 << regno; + } + inline void mark_def (int regno) { @@ -722,11 +728,11 @@ insn_info::scan () if (sz <= 64) { mark_hard (0); - mark_use (0); + mark_myuse (0); if (sz > 32) { mark_hard (1); - mark_use (1); + mark_myuse (1); } } } @@ -739,7 +745,7 @@ insn_info::scan () if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) - mark_use (r); + mark_myuse (r); } /* mark scratch registers. */ mark_def (0); @@ -759,13 +765,13 @@ insn_info::scan_rtx (rtx x) if (REG_P(x)) { for (int n = REG_NREGS(x), r = REGNO(x); n > 0; --n, ++r) - mark_use (r); + mark_myuse (r); return; } if (x == cc0_rtx) { - mark_use (FIRST_PSEUDO_REGISTER); + mark_myuse (FIRST_PSEUDO_REGISTER); return; } @@ -1019,7 +1025,7 @@ typedef std::multimap::iterator j2l_iterator; static std::map insn2info; typedef std::map::iterator i2i_iterator; -static std::set returns; +static std::set scan_starts; typedef std::set::iterator su_iterator; static insn_info * info0; @@ -1137,7 +1143,7 @@ insn_info::a5_to_a7 (rtx a7) rtx set = single_set (insn); if (set) { - SET_SRC(set) = gen_rtx_MEM(mode, gen_rtx_POST_INC(SImode, a7)); + SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC(SImode, a7)); return; } } @@ -1221,7 +1227,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) SET_INSN_DELETED(insn); insn = emit_insn_after (pattern, insn); - mark_use (regno); + mark_myuse (regno); insn2info.insert (std::make_pair (insn, this)); } @@ -1235,7 +1241,7 @@ clear (void) jump2label.clear (); insn2info.clear (); infos.clear (); - returns.clear (); + scan_starts.clear (); } /* @@ -1348,9 +1354,7 @@ static void update_insn_infos (void) { /* add all return (jump outs) and start analysis there. */ - std::set todo; - for (su_iterator i = returns.begin (); i != returns.end (); ++i) - todo.insert (*i); + std::set & todo = scan_starts; if (todo.begin () == todo.end ()) todo.insert (infos.size () - 1); @@ -1417,12 +1421,13 @@ update_insn_infos (void) insn_info use (insn); use.scan (); + /* do not mark a node as visited, if it's in epilogue and not yet visited. */ if (CALL_P(insn) || JUMP_P(insn)) { - if (pos != start) + if (pos != start && ii.in_proepi ()) { - su_iterator k = returns.find (pos); - if (k != returns.end ()) + su_iterator k = scan_starts.find (pos); + if (k != scan_starts.end ()) { pp.clear_visited (); break; @@ -1510,7 +1515,7 @@ update_insns () { if (inproepilogue || ANY_RETURN_P(PATTERN (insn))) { - returns.insert (infos.size () - 1); + scan_starts.insert (infos.size () - 1); inproepilogue = IN_CODE; rtx set = single_set (insn); if (ANY_RETURN_P(PATTERN (insn)) @@ -1579,13 +1584,15 @@ update_insns () ii.mark_label (); jump_table = 0; ii.set_proepi (inproepilogue = IN_CODE); + if (infos.size () > 1) + scan_starts.insert (infos.size () - 1); } else if (CALL_P(insn)) { ii.mark_call (); if (inproepilogue) { - returns.insert (infos.size () - 1); + scan_starts.insert (infos.size () - 1); inproepilogue = IN_CODE; } } @@ -1614,7 +1621,7 @@ update_insns () inproepilogue = IN_EPILOGUE; } } - + scan_starts.insert (infos.size () - 1); update_insn2index (); update_insn_infos (); @@ -1666,14 +1673,17 @@ find_start (std::set & found, unsigned start, unsigned rename_regno) break; /* do not run over RETURNS */ - rtx_insn * before = infos[startm1].get_insn (); - if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before))) + insn_info & jj = infos[start]; + insn_info & bb = infos[startm1]; + if (jj.in_proepi () == IN_CODE && bb.in_proepi () >= IN_EPILOGUE) break; +// rtx_insn * before = infos[startm1].get_insn (); +// if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before))) +// break; start = startm1; /* found the definition without use. */ - insn_info & jj = infos[start]; if (jj.is_def (rename_regno) && !jj.is_use (rename_regno)) break; @@ -3351,6 +3361,8 @@ opt_absolute (void) else log ("(b) modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]); + unsigned current_use = ii.get_use (); + for (std::vector::iterator k = found.begin (); k != found.end (); ++k) { insn_info & kk = infos[*k]; @@ -3373,7 +3385,7 @@ opt_absolute (void) lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); insn_info nn (insn); - nn.set_use (ii.get_use ()); + nn.set_use (current_use); nn.scan (); nn.fledder (lea); nn.mark_def (regno); @@ -3496,7 +3508,7 @@ namespace done = 0, update_insns (); if (do_absolute && opt_absolute ()) - done = 0; + done = 0, update_insns (); if (do_bb_reg_rename) { From 21a94abb83e5a01f912dbc66951cc32797d05ed3 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 2 Jun 2017 20:11:26 +0200 Subject: [PATCH 156/303] @B fix opt_reg_rename: backward search for defs was off by one @N startet to add register tracking --- gcc/bbb-opts.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 193 insertions(+), 43 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 26ca56bbb84d..9014295f8b43 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -167,16 +167,31 @@ class insn_info int dst_autoinc; int src_autoinc; + // values for all variables - if used + rtx * values; + public: insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol ( 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited ( - false), sp_offset (0), dst_autoinc (0), src_autoinc (0) + false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0) { } + void + set_values (rtx * v); + + bool + merge_values (rtx * v); + + bool + equal_values (rtx * v) const; + + rtx + get_value_for (unsigned regno) const; + inline ptrdiff_t operator < (insn_info const & o) const { @@ -421,7 +436,7 @@ class insn_info return stack; } - inline int + inline enum proepis in_proepi () const { return proepi; @@ -716,6 +731,56 @@ class insn_info a5_to_a7 (rtx a7); }; +void +insn_info::set_values (rtx * v) +{ + if (!values) + values = new rtx[16]; + memcpy (values, v, 16 * sizeof(rtx)); +} + +static const rtx INVALID = (rtx) -1; + +bool +insn_info::merge_values (rtx * v) +{ + bool r = false; + if (!values) + r = true, set_values (v); + else + for (int i = 0; i < 16; ++i) + if (!values[i]) + r = true, values[i] = v[i]; + else if (values[i] != INVALID && v[i] && v[i] != INVALID && !rtx_equal_p (values[i], v[i])) + r = true, values[i] = INVALID; + return r; +} + +bool +insn_info::equal_values (rtx * v) const +{ + if (!values) + return false; + for (int i = 0; i < 16; ++i) + if (values[i] && !v[i]) + return false; + else if (v[i] && !values[i]) + return false; + else if (values[i] == INVALID && v[i] != INVALID) + return false; + else if (!rtx_equal_p (values[i], v[i])) + return false; + return true; +} + +rtx +insn_info::get_value_for (unsigned regno) const +{ + if (!values || regno > 15) + return 0; + return values[regno]; +} + void insn_info::scan () { @@ -1365,13 +1430,18 @@ update_insn_infos (void) todo.erase (todo.begin ()); insn_info ii = infos[start]; + enum proepis proepi = ii.in_proepi (); + for (int pos = start; pos >= 0; --pos) { insn_info & pp = infos[pos]; rtx_insn * insn = pp.get_insn (); - /* can be NULL as used in opt_shrink_stack_frame(). */ - if (!insn) - continue; + + // do not run into previous epilogue + if (pp.in_proepi () >= IN_EPILOGUE && !proepi) + break; + + proepi = pp.in_proepi (); /* no new information -> break. */ if (pos != start && pp.is_visited () && !JUMP_P(insn) && pp.contains (ii)) @@ -1677,16 +1747,12 @@ find_start (std::set & found, unsigned start, unsigned rename_regno) insn_info & bb = infos[startm1]; if (jj.in_proepi () == IN_CODE && bb.in_proepi () >= IN_EPILOGUE) break; -// rtx_insn * before = infos[startm1].get_insn (); -// if (JUMP_P(before) && ANY_RETURN_P(PATTERN (before))) -// break; - - start = startm1; /* found the definition without use. */ if (jj.is_def (rename_regno) && !jj.is_use (rename_regno)) break; + start = startm1; } return start; } @@ -2531,39 +2597,6 @@ opt_const_cmp_to_sub (void) return change_count; } -/* - * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop. - * delete those insns. - */ -static unsigned -opt_elim_dead_assign (void) -{ - unsigned change_count = 0; - for (int index = infos.size () - 1; index >= 0; --index) - { - rtx_insn * insn = infos[index].get_insn (); - if (!NONJUMP_INSN_P(insn)) - continue; - - rtx set = single_set (insn); - if (!set) - continue; - - rtx src = SET_SRC(set); - rtx dst = SET_DEST(set); - if (!REG_P(dst) || !REG_P(src)) - continue; - - if (is_reg_dead (REGNO(dst), index)) - { - log ("(e) %d: elim_dead_assign to %s\n", index, reg_names[REGNO(dst)]); - SET_INSN_DELETED(insn); - ++change_count; - } - } - return change_count; -} - /* * rare and only little gain - but :-) lea (-1,a0),a1 @@ -3233,6 +3266,123 @@ opt_shrink_stack_frame (void) return changed; } +/* Update the insn_infos to 'know' the value for each register. */ +static unsigned +track_regs () +{ + // reset visited flags + for (unsigned index = 0; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + ii.clear_visited (); + ii.set_sp_offset (0); + } + + // add entry point + std::set todo; + todo.insert (0); + + while (todo.begin () != todo.end ()) + { + unsigned startpos = *todo.begin (); + todo.erase (todo.begin ()); + + rtx * values = new rtx[16]; // track dx/ax + memset (values, 0, 16 * sizeof(rtx)); + + for (unsigned index = startpos; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + + // already visited? + if (ii.is_visited () && ii.equal_values (values)) + break; + + // mark current insn_info and set sp_offset + ii.mark_visited (); + + ii.merge_values (values); + + // add all referred labels + if (ii.is_jump ()) + { + for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i) + { + todo.insert (i->second); + insn_info & jj = infos[i->second]; + if (jj.merge_values (values)) + ii.clear_visited (); + } + continue; + } + + // track register values for now + int regno = ii.get_dst_regno (); + if (regno < 0) + { + // TODO: track if dst_mem is volatile + continue; + } + + rtx set = single_set (ii.get_insn ()); + if (!set) + continue; + + rtx src = SET_SRC(set); + + // TODO: check for volatile sources + values[regno] = src; + + for (int i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) + values[regno] = INVALID; + } + } + return 0; +} + +/* + * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop. + * delete those insns. + */ +static unsigned +opt_elim_dead_assign (void) +{ + track_regs (); + + unsigned change_count = 0; + for (int index = infos.size () - 1; index >= 0; --index) + { + insn_info & ii = infos[index]; + if (!ii.get_dst_reg ()) + continue; + + rtx_insn * insn = ii.get_insn (); + rtx set = single_set (insn); + if (!set) + + if (ii.get_src_reg () && is_reg_dead (ii.get_dst_regno (), index)) + { + log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; + } + + continue; + + rtx cached_value = ii.get_value_for (ii.get_dst_regno ()); + if (cached_value && cached_value != INVALID && rtx_equal_p (cached_value, SET_SRC(set))) + { + log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; + + } + } + return change_count; +} + /* * Convert a series of move into absolute address into register based moves. */ From 98fb7816dc4ef9e568a068343dbcf331ccdca4d0 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 3 Jun 2017 17:40:50 +0200 Subject: [PATCH 157/303] @B fix opt_shrink_stack_frame: not all sp offsets were patched --- gcc/bbb-opts.c | 120 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 74 insertions(+), 46 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9014295f8b43..00ac220456b2 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -146,6 +146,7 @@ class insn_info bool src_plus; rtx_code src_op; bool src_ee; + bool src_2nd; bool src_const; machine_mode mode; @@ -174,9 +175,9 @@ class insn_info insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) : insn (i), myuse (0), hard (0), use (0), def (0), proepi (p), stack (false), label (false), jump (false), call ( false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( - (rtx_code) 0), src_ee (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg (0), dst_symbol ( - 0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr (0), visited ( - false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0) + (rtx_code) 0), src_ee (false), src_2nd (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg ( + 0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr ( + 0), visited (false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0) { } @@ -240,6 +241,12 @@ class insn_info return src_mem; } + inline bool + is_src_mem_2nd () const + { + return src_2nd && src_mem; + } + inline bool has_dst_memreg () const { @@ -408,6 +415,9 @@ class insn_info void fledder (rtx set); + void + fledder_src_mem (rtx src); + /* update usage. */ void update (insn_info & o) @@ -872,6 +882,51 @@ insn_info::scan_rtx (rtx x) } } +void +insn_info::fledder_src_mem (rtx src) +{ + src_mem = true; + rtx mem = XEXP(src, 0); + + if (GET_CODE(mem) == POST_INC) + src_autoinc = 1, mem = XEXP(mem, 0); + else if (GET_CODE(mem) == PRE_DEC) + src_autoinc = -1, mem = XEXP(mem, 0); + + if (REG_P(mem)) + src_mem_reg = mem; + else if (GET_CODE(mem) == CONST_INT) + src_mem_addr = INTVAL(mem); + else if (GET_CODE(mem) == SYMBOL_REF) + src_symbol = mem; + else if (GET_CODE(mem) == PLUS) + { + src_plus = true; + rtx reg = XEXP(mem, 0); + rtx konst = XEXP(mem, 1); + if (REG_P(reg) && GET_CODE(konst) == CONST_INT) + { + src_mem_reg = reg; + src_const = true; + src_mem_addr = INTVAL(konst); + } + } + else if (GET_CODE(mem) == CONST) + { + mem = XEXP(mem, 0); + if (GET_CODE(mem) == PLUS) + { + rtx sym = XEXP(mem, 0); + if (GET_CODE(sym) == SYMBOL_REF) + { + src_plus = true; + src_symbol = sym; + src_mem_addr = INTVAL(XEXP(mem, 1)); + } + } + } +} + /* read the set and grab infos */ void insn_info::fledder (rtx set) @@ -959,7 +1014,15 @@ insn_info::fledder (rtx set) if (GET_CODE(operand) == CONST_INT || GET_CODE(operand) == CONST_WIDE_INT) src_const = true, src_intval = INTVAL(operand); else if (REG_P(operand)) - alt_src_reg = operand; + { + alt_src_reg = operand; + } + else if (MEM_P(operand)) + { + // it' something like reg = op(reg, mem(...)) + src_2nd = true; + fledder_src_mem (operand); + } } src = XEXP(src, 0); } @@ -970,46 +1033,7 @@ insn_info::fledder (rtx set) } else if (MEM_P(src)) { - src_mem = true; - rtx mem = XEXP(src, 0); - - if (GET_CODE(mem) == POST_INC) - src_autoinc = 1, mem = XEXP(mem, 0); - else if (GET_CODE(mem) == PRE_DEC) - src_autoinc = -1, mem = XEXP(mem, 0); - - if (REG_P(mem)) - src_mem_reg = mem; - else if (GET_CODE(mem) == CONST_INT) - src_mem_addr = INTVAL(mem); - else if (GET_CODE(mem) == SYMBOL_REF) - src_symbol = mem; - else if (GET_CODE(mem) == PLUS) - { - src_plus = true; - rtx reg = XEXP(mem, 0); - rtx konst = XEXP(mem, 1); - if (REG_P(reg) && GET_CODE(konst) == CONST_INT) - { - src_mem_reg = reg; - src_const = true; - src_mem_addr = INTVAL(konst); - } - } - else if (GET_CODE(mem) == CONST) - { - mem = XEXP(mem, 0); - if (GET_CODE(mem) == PLUS) - { - rtx sym = XEXP(mem, 0); - if (GET_CODE(sym) == SYMBOL_REF) - { - src_plus = true; - src_symbol = sym; - src_mem_addr = INTVAL(XEXP(mem, 1)); - } - } - } + fledder_src_mem (src); } else if (GET_CODE(src) == CONST_INT) { @@ -3173,7 +3197,11 @@ opt_shrink_stack_frame (void) rtx src = XEXP(pattern, 1); rtx plus = XEXP(src, 0); if (ii.get_src_op ()) - plus = XEXP(plus, 0); + { + plus = XEXP(src, 1); + if (MEM_P(plus)) + plus = XEXP(plus, 0); + } XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_src_mem_addr () - adjust); } @@ -3333,7 +3361,7 @@ track_regs () // TODO: check for volatile sources values[regno] = src; - for (int i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) + for (unsigned i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) values[regno] = INVALID; } } From 3d0257b6111e90dab6f704f81bb6c0a5adc3191f Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 3 Jun 2017 19:01:51 +0100 Subject: [PATCH 158/303] @V bump datestamp --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index b5d1e40685b6..54bc2fee3dce 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170529-215512 +20170603-190132 From a64448fa986d1e9e89b7214926213844749cb330 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 4 Jun 2017 10:54:35 +0200 Subject: [PATCH 159/303] @B removed bogus (and not yet used) code --- gcc/bbb-opts.c | 86 ---------------------------------------------------------- 1 file changed, 86 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 00ac220456b2..11c3891025e9 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3294,80 +3294,6 @@ opt_shrink_stack_frame (void) return changed; } -/* Update the insn_infos to 'know' the value for each register. */ -static unsigned -track_regs () -{ - // reset visited flags - for (unsigned index = 0; index < infos.size (); ++index) - { - insn_info & ii = infos[index]; - ii.clear_visited (); - ii.set_sp_offset (0); - } - - // add entry point - std::set todo; - todo.insert (0); - - while (todo.begin () != todo.end ()) - { - unsigned startpos = *todo.begin (); - todo.erase (todo.begin ()); - - rtx * values = new rtx[16]; // track dx/ax - memset (values, 0, 16 * sizeof(rtx)); - - for (unsigned index = startpos; index < infos.size (); ++index) - { - insn_info & ii = infos[index]; - - // already visited? - if (ii.is_visited () && ii.equal_values (values)) - break; - - // mark current insn_info and set sp_offset - ii.mark_visited (); - - ii.merge_values (values); - - // add all referred labels - if (ii.is_jump ()) - { - for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i) - { - todo.insert (i->second); - insn_info & jj = infos[i->second]; - if (jj.merge_values (values)) - ii.clear_visited (); - } - continue; - } - - // track register values for now - int regno = ii.get_dst_regno (); - if (regno < 0) - { - // TODO: track if dst_mem is volatile - continue; - } - - rtx set = single_set (ii.get_insn ()); - if (!set) - continue; - - rtx src = SET_SRC(set); - - // TODO: check for volatile sources - values[regno] = src; - - for (unsigned i = regno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) - values[regno] = INVALID; - } - } - return 0; -} - /* * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop. * delete those insns. @@ -3375,8 +3301,6 @@ track_regs () static unsigned opt_elim_dead_assign (void) { - track_regs (); - unsigned change_count = 0; for (int index = infos.size () - 1; index >= 0; --index) { @@ -3397,16 +3321,6 @@ opt_elim_dead_assign (void) } continue; - - rtx cached_value = ii.get_value_for (ii.get_dst_regno ()); - if (cached_value && cached_value != INVALID && rtx_equal_p (cached_value, SET_SRC(set))) - { - log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); - SET_INSN_DELETED(insn); - ++change_count; - continue; - - } } return change_count; } From 5a66c60ad7bba806de2640310c4e3e4941245aa2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 5 Jun 2017 00:00:30 +0200 Subject: [PATCH 160/303] @B fix reg use/def marking in ASM_SPEC, @B rewrote SP offset patcher, @N added variable tracking and (e)liminate redundat load --- gcc/bbb-opts.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 251 insertions(+), 45 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 11c3891025e9..e9a8df7d1c01 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -181,6 +181,9 @@ class insn_info { } + rtx * + get_values (); + void set_values (rtx * v); @@ -741,12 +744,23 @@ class insn_info a5_to_a7 (rtx a7); }; +rtx * +insn_info::get_values () +{ + if (values) + return values; + + values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); + memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx)); + return values; +} + void insn_info::set_values (rtx * v) { if (!values) - values = new rtx[16]; - memcpy (values, v, 16 * sizeof(rtx)); + values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); + memcpy (values, v, FIRST_PSEUDO_REGISTER * sizeof(rtx)); } static const rtx INVALID = (rtx) -1; @@ -758,7 +772,7 @@ insn_info::merge_values (rtx * v) if (!values) r = true, set_values (v); else - for (int i = 0; i < 16; ++i) + for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (!values[i]) r = true, values[i] = v[i]; else if (values[i] != INVALID && v[i] && v[i] != INVALID && !rtx_equal_p (values[i], v[i])) @@ -771,7 +785,7 @@ insn_info::equal_values (rtx * v) const { if (!values) return false; - for (int i = 0; i < 16; ++i) + for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (values[i] && !v[i]) return false; else if (v[i] && !values[i]) @@ -857,6 +871,7 @@ insn_info::scan_rtx (rtx x) { unsigned u = use; unsigned mu = myuse; + use = myuse = 0; scan_rtx (SET_DEST(x)); if (REG_P(SET_DEST(x))) { @@ -867,7 +882,7 @@ insn_info::scan_rtx (rtx x) scan_rtx (SET_SRC(x)); int code = GET_CODE(SET_SRC(x)); if (code == ASM_OPERANDS) - use = hard |= def | use; + hard |= def | use; return; } @@ -878,7 +893,15 @@ insn_info::scan_rtx (rtx x) scan_rtx (XEXP(x, i)); else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - scan_rtx (XVECEXP(x, i, j)); + { + unsigned u = use; + unsigned mu = myuse; + unsigned d = def; + scan_rtx (XVECEXP(x, i, j)); + use |= u; + myuse |= myuse; + def |= d; + } } } @@ -2775,6 +2798,33 @@ track_sp () return 0; } +/* recursive function to patch stack pointer offsets. */ +void +patch_sp (rtx x, int adjust, int spoffset) +{ + int code = GET_CODE(x); + if (code == PLUS) + { + rtx a = XEXP(x, 0); + rtx b = XEXP(x, 1); + if (REG_P(a) && REGNO(a) == STACK_POINTER_REGNUM && GET_CODE(b) == CONST_INT) + { + if (INTVAL(b) > -spoffset) + XEXP(x, 1) = gen_rtx_CONST_INT (GET_MODE(b), INTVAL(b) - adjust); + return; + } + } + const char *fmt = GET_RTX_FORMAT(code); + for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + patch_sp (XEXP(x, i), adjust, spoffset); + else if (fmt[i] == 'E') + for (int j = XVECLEN (x, i) - 1; j >= 0; j--) + patch_sp (XVECEXP(x, i, j), adjust, spoffset); + } +} + /** * 1. scan for all used registers. * 2. scan the stack from for omittable push/pop @@ -3179,37 +3229,8 @@ opt_shrink_stack_frame (void) continue; rtx pattern = single_set (ii.get_insn ()); - if (ii.is_compare ()) - pattern = XEXP(pattern, 1); - - // lea n(sp),ax - if (ii.get_src_reg () && ii.get_src_regno () == STACK_POINTER_REGNUM && ii.get_src_op () == PLUS) - { - // touch only if above pushed parameters - if (ii.get_src_intval () > -ii.get_sp_offset ()) - { - rtx src = XEXP(pattern, 1); - XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), ii.get_src_intval () - adjust); - } - } - else if (ii.is_src_mem () && ii.is_src_mem_plus () && ii.get_src_mem_regno () == STACK_POINTER_REGNUM) - { - rtx src = XEXP(pattern, 1); - rtx plus = XEXP(src, 0); - if (ii.get_src_op ()) - { - plus = XEXP(src, 1); - if (MEM_P(plus)) - plus = XEXP(plus, 0); - } - XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_src_mem_addr () - adjust); - } - - if (ii.is_dst_mem () && ii.is_dst_mem_plus () && ii.get_dst_mem_regno () == STACK_POINTER_REGNUM) - { - rtx plus = XEXP(XEXP(pattern, 0), 0); - XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), ii.get_dst_intval () - adjust); - } + if (pattern) + patch_sp (pattern, adjust, ii.get_sp_offset ()); } } @@ -3294,6 +3315,168 @@ opt_shrink_stack_frame (void) return changed; } +/* Update the insn_infos to 'know' the value for each register. */ +static unsigned +track_regs () +{ + // reset visited flags + for (unsigned index = 0; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + ii.clear_visited (); + ii.set_sp_offset (0); + } + + rtx * values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); // track register values + + // add entry point + std::set todo; + todo.insert (0); + + while (todo.begin () != todo.end ()) + { + unsigned startpos = *todo.begin (); + todo.erase (todo.begin ()); + + memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx)); + + // track register aliases: know which register refers to this slot + // if a register changes, invalidate each referrer + std::multimap r2r; + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + if (values[i] && values[i] != INVALID && REG_P(values[i])) + r2r.insert (std::make_pair (REGNO(values[i]), i)); + + for (unsigned index = startpos; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + + // already visited? + if (ii.is_visited () && ii.equal_values (values)) + break; + + // mark current insn_info and set sp_offset + ii.mark_visited (); + + // do not optimize over labels + if (ii.is_label ()) + { + memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx)); + continue; + } + + ii.merge_values (values); + + if (ii.is_compare ()) + continue; + + unsigned def = ii.get_def (); + if (def) + { + for (int i = 0; i < 16; ++i) + if ((1 << i) & def) + { + values[i] = 0; + // invalidate all referring registers + for (std::multimap::iterator j = r2r.find (i), k = j; + j != r2r.end () && j->first == k->first;) + { + values[j->second] = INVALID; + r2r.erase (j++); + } + } + } + + if (ii.is_call ()) + continue; + + // add all referred labels + if (ii.is_jump ()) + { + for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i) + { + todo.insert (i->second); + insn_info & jj = infos[i->second]; + if (jj.merge_values (values)) + ii.clear_visited (); + } + continue; + } + + rtx set = single_set (ii.get_insn ()); + if (!set) + continue; + + rtx src, dest; + if (ii.get_src_autoinc ()) + { + int regno = ii.get_src_mem_regno (); + values[regno] = INVALID; + for (std::multimap::iterator j = r2r.find (regno), k = j; + j != r2r.end () && j->first == k->first;) + { + values[j->second] = INVALID; + r2r.erase (j++); + } + } + + if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ())) + src = INVALID; + else + { + src = SET_SRC(set); + if (ii.is_src_mem () && src->volatil) + src = INVALID; + } + + if (ii.get_dst_autoinc ()) + { + int regno = ii.get_dst_mem_regno (); + values[regno] = INVALID; + for (std::multimap::iterator j = r2r.find (regno), k = j; + j != r2r.end () && j->first == k->first;) + { + values[j->second] = INVALID; + r2r.erase (j++); + } + } + + if (src == INVALID || ii.get_src_op () || ii.get_dst_autoinc ()) + dest = INVALID; + else + dest = SET_DEST(set); + + // track register values for now + int dregno = ii.get_dst_regno (); + int sregno = ii.get_src_regno (); + + // track r2r + if (dregno >= 0 && sregno >= 0) + { + r2r.insert (std::make_pair (dregno, sregno)); + r2r.insert (std::make_pair (sregno, dregno)); + } + + if (sregno >= 0) + { + values[sregno] = dest; + for (unsigned i = sregno + 1; i < END_REGNO (ii.get_src_reg ()); ++i) + values[i] = INVALID; + } + + if (dregno >= 0) + { + // TODO: check for volatile sources + values[dregno] = src; + for (unsigned i = dregno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) + values[i] = INVALID; + + } + } + } + return 0; +} + /* * Some optimizations (e.g. propagate_moves) might result into an unused assignment behind the loop. * delete those insns. @@ -3301,11 +3484,13 @@ opt_shrink_stack_frame (void) static unsigned opt_elim_dead_assign (void) { + track_regs (); + unsigned change_count = 0; for (int index = infos.size () - 1; index >= 0; --index) { insn_info & ii = infos[index]; - if (!ii.get_dst_reg ()) + if (!ii.get_dst_reg () || ii.is_compare ()) continue; rtx_insn * insn = ii.get_insn (); @@ -3319,8 +3504,23 @@ opt_elim_dead_assign (void) ++change_count; continue; } + if (ii.get_src_op () == 0) + { + rtx cached_value = ii.get_value_for (ii.get_dst_regno ()); + rtx cached_value2 = 0; + if (cached_value && cached_value != INVALID && REG_P(cached_value) && REGNO(cached_value) < 16) + cached_value2 = ii.get_value_for (REGNO(cached_value)); + if (cached_value && cached_value != INVALID + && (rtx_equal_p (cached_value, SET_SRC(set)) + || (cached_value2 && cached_value2 != INVALID && rtx_equal_p (cached_value2, SET_SRC(set))))) + { + log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; - continue; + } + } } return change_count; } @@ -3360,8 +3560,8 @@ opt_absolute (void) std::vector found; found.push_back (i); - unsigned base = ii.get_dst_addr (); - unsigned max = base; + int base = ii.get_dst_addr (); + int max = base; unsigned j = i + 1; for (; j < infos.size (); ++j) { @@ -3393,7 +3593,7 @@ opt_absolute (void) if (j_dst) { - unsigned addr = jj.get_dst_addr (); + int addr = jj.get_dst_addr (); if (addr < base) { if (max - addr <= 0x7ffe) @@ -3413,7 +3613,7 @@ opt_absolute (void) } if (j_src) { - unsigned addr = jj.get_src_mem_addr (); + int addr = jj.get_src_mem_addr (); if (addr < base) { if (max - addr <= 0x7ffe) @@ -3439,8 +3639,14 @@ opt_absolute (void) for (std::vector::iterator k = found.begin (); k != found.end ();) { insn_info & kk = infos[*k]; - if (kk.get_dst_addr () - base > 0x7ffc) - found.erase (k); + bool k_dst = kk.is_dst_mem () && (kk.has_dst_addr () || kk.get_dst_symbol ()) && !kk.has_dst_memreg () + && kk.get_dst_symbol () == with_symbol; + bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg () + && kk.get_src_symbol () == with_symbol; + if (k_dst && kk.get_dst_addr () - base > 0x7ffc) + found.erase (k++); + else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc) + found.erase (k++); else ++k; } From 09bb1d02257cbc120bb9f2fa8d4b49999662f328 Mon Sep 17 00:00:00 2001 From: fautomat Date: Mon, 5 Jun 2017 09:10:12 +0100 Subject: [PATCH 161/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 54bc2fee3dce..cb00f5c9a36e 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170603-190132 +20170605-091011 From 9be210ab91c70ab5776d8e01fb4c63e8b7695a0f Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 6 Jun 2017 16:56:04 +0200 Subject: [PATCH 162/303] @I improve the algorithm to find redundant register loads --- gcc/bbb-opts.c | 280 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 153 insertions(+), 127 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index e9a8df7d1c01..6fc53c674a4d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -116,6 +116,76 @@ enum proepis IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP }; +class track_var +{ + rtx * values; + unsigned * versions; + +public: + track_var (track_var const * o = 0) : + values ((rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions ( + (unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))) + { + if (o) + assign (o); + } + + rtx * + get_values () const + { + return values; + } + + void + set_version (unsigned regno, unsigned ver) + { + if (regno < FIRST_PSEUDO_REGISTER) + versions[regno] = ver; + } + + void + assign (track_var const * o) const + { + memcpy (values, o->values, FIRST_PSEUDO_REGISTER * sizeof(rtx)); + memcpy (versions, o->versions, FIRST_PSEUDO_REGISTER * sizeof(unsigned)); + } + + /* only keep common values in both sides. */ + void + merge (track_var * o) + { + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i])) + { + int code = GET_CODE(values[i]); + if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i]) + values[i] = o->values[i] = 0; + } + else + values[i] = o->values[i] = 0; + } + } + + /* true if a merge would not change anything. */ + bool + contains (track_var const * o) const + { + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i])) + { + int code = GET_CODE(values[i]); + if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i]) + return false; + } + else if (values[i]) + return false; + } + return true; + } +}; + /* Information for each insn to detect alive registers. Enough for m68k. * Why a class? Maybe extend it for general usage. * @@ -125,7 +195,7 @@ class insn_info { rtx_insn * insn; // the insn - // usage flags +// usage flags unsigned myuse; // bit set if registers are used in this statement unsigned hard; // bit set if registers can't be renamed unsigned use; // bit set if registers are used in program flow @@ -135,7 +205,7 @@ class insn_info bool stack; // part of stack frame insns - // stuff to analyze insns +// stuff to analyze insns bool label; bool jump; bool call; @@ -168,8 +238,8 @@ class insn_info int dst_autoinc; int src_autoinc; - // values for all variables - if used - rtx * values; +// values for all variables - if used + track_var * track; public: insn_info (rtx_insn * i = 0, enum proepis p = IN_CODE) : @@ -177,24 +247,12 @@ class insn_info false), compare (false), dst_mem (false), src_mem (false), dst_plus (false), src_plus (false), src_op ( (rtx_code) 0), src_ee (false), src_2nd (false), src_const (false), mode (VOIDmode), dst_reg (0), dst_mem_reg ( 0), dst_symbol (0), src_reg (0), src_mem_reg (0), src_symbol (0), dst_mem_addr (0), src_intval (0), src_mem_addr ( - 0), visited (false), sp_offset (0), dst_autoinc (0), src_autoinc (0), values (0) + 0), visited (false), sp_offset (0), dst_autoinc (0), src_autoinc (0), track (0) { } - rtx * - get_values (); - - void - set_values (rtx * v); - - bool - merge_values (rtx * v); - - bool - equal_values (rtx * v) const; - - rtx - get_value_for (unsigned regno) const; + track_var * + get_track_var (); inline ptrdiff_t operator < (insn_info const & o) const @@ -744,65 +802,12 @@ class insn_info a5_to_a7 (rtx a7); }; -rtx * -insn_info::get_values () +track_var * +insn_info::get_track_var () { - if (values) - return values; - - values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); - memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx)); - return values; -} - -void -insn_info::set_values (rtx * v) -{ - if (!values) - values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); - memcpy (values, v, FIRST_PSEUDO_REGISTER * sizeof(rtx)); -} - -static const rtx INVALID = (rtx) -1; - -bool -insn_info::merge_values (rtx * v) -{ - bool r = false; - if (!values) - r = true, set_values (v); - else - for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - if (!values[i]) - r = true, values[i] = v[i]; - else if (values[i] != INVALID && v[i] && v[i] != INVALID && !rtx_equal_p (values[i], v[i])) - r = true, values[i] = INVALID; - return r; -} - -bool -insn_info::equal_values (rtx * v) const -{ - if (!values) - return false; - for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - if (values[i] && !v[i]) - return false; - else if (v[i] && !values[i]) - return false; - else if (values[i] == INVALID && v[i] != INVALID) - return false; - else if (!rtx_equal_p (values[i], v[i])) - return false; - return true; -} - -rtx -insn_info::get_value_for (unsigned regno) const -{ - if (!values || regno > 15) - return 0; - return values[regno]; + if (!track) + track = new track_var (); + return track; } void @@ -899,7 +904,7 @@ insn_info::scan_rtx (rtx x) unsigned d = def; scan_rtx (XVECEXP(x, i, j)); use |= u; - myuse |= myuse; + myuse |= mu; def |= d; } } @@ -1185,12 +1190,12 @@ insn_info::get_index () const return pos; } - // realloc happened... +// realloc happened... for (unsigned i = 0; i < infos.size (); ++i) if (infos[i].get_insn () == this->insn) return i; - // whoops!? +// whoops!? return 0; } @@ -1201,7 +1206,7 @@ insn_info::plus_to_move (rtx_insn * newinsn) src_op = (rtx_code) 0; src_reg = XEXP(PATTERN (newinsn), 1); insn2info.insert (std::make_pair (insn, this)); - // usage flags did not change +// usage flags did not change } void @@ -1214,7 +1219,7 @@ insn_info::swap_adds (rtx_insn * newinsn, insn_info & ii) insn2info.insert (std::make_pair (insn, this)); insn2info.insert (std::make_pair (ii.insn, &ii)); - // usage flags did not change +// usage flags did not change } static @@ -1363,7 +1368,7 @@ clear (void) static bool is_reg_dead (unsigned regno, unsigned _pos) { - // skip labels. +// skip labels. for (unsigned pos = _pos + 1; pos < infos.size (); ++pos) { insn_info & ii0 = infos[pos]; @@ -2719,7 +2724,7 @@ opt_merge_add (void) static unsigned track_sp () { - // reset visited flags +// reset visited flags for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; @@ -2727,7 +2732,7 @@ track_sp () ii.set_sp_offset (0); } - // add entry point +// add entry point std::set todo; todo.insert (0); @@ -3319,7 +3324,7 @@ opt_shrink_stack_frame (void) static unsigned track_regs () { - // reset visited flags +// reset visited flags for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; @@ -3327,45 +3332,59 @@ track_regs () ii.set_sp_offset (0); } - rtx * values = (rtx *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof(rtx)); // track register values + update_label2jump (); - // add entry point - std::set todo; - todo.insert (0); +// add entry point + std::map todo; + todo.insert (std::make_pair (0, new track_var ())); while (todo.begin () != todo.end ()) { - unsigned startpos = *todo.begin (); + unsigned startpos = todo.begin ()->first; + track_var * const track = todo.begin ()->second; todo.erase (todo.begin ()); - memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx)); - + rtx * values = track->get_values (); // track register aliases: know which register refers to this slot // if a register changes, invalidate each referrer std::multimap r2r; for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - if (values[i] && values[i] != INVALID && REG_P(values[i])) + if (values[i] && REG_P(values[i])) r2r.insert (std::make_pair (REGNO(values[i]), i)); + unsigned version = startpos; + for (unsigned index = startpos; index < infos.size (); ++index) { insn_info & ii = infos[index]; // already visited? - if (ii.is_visited () && ii.equal_values (values)) + if (ii.is_visited () && ii.get_track_var ()->contains (track)) break; - // mark current insn_info and set sp_offset - ii.mark_visited (); - - // do not optimize over labels + // only keep common values at labels if (ii.is_label ()) { - memset (values, 0xff, FIRST_PSEUDO_REGISTER * sizeof(rtx)); + version = index; + if (ii.is_visited ()) + { + ii.get_track_var ()->merge (track); + r2r.clear (); + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + if (values[i] && REG_P(values[i])) + r2r.insert (std::make_pair (REGNO(values[i]), i)); + } + else + { + ii.get_track_var ()->assign (track); + ii.mark_visited (); + } continue; } - ii.merge_values (values); + // mark current insn_info and set sp_offset + ii.mark_visited (); + ii.get_track_var ()->assign (track); if (ii.is_compare ()) continue; @@ -3381,7 +3400,7 @@ track_regs () for (std::multimap::iterator j = r2r.find (i), k = j; j != r2r.end () && j->first == k->first;) { - values[j->second] = INVALID; + values[j->second] = 0; r2r.erase (j++); } } @@ -3390,20 +3409,27 @@ track_regs () if (ii.is_call ()) continue; + rtx set = single_set (ii.get_insn ()); + // add all referred labels if (ii.is_jump ()) { + if (ANY_RETURN_P(ii.get_insn ())) + break; + for (j2l_iterator i = jump2label.find (index), k = i; i != jump2label.end () && i->first == k->first; ++i) + todo.insert (std::make_pair (i->second, new track_var (track))); + + if (set && GET_CODE(SET_SRC(set)) == IF_THEN_ELSE) { - todo.insert (i->second); - insn_info & jj = infos[i->second]; - if (jj.merge_values (values)) - ii.clear_visited (); + version = index; + continue; } - continue; + + // unconditional jump + break; } - rtx set = single_set (ii.get_insn ()); if (!set) continue; @@ -3411,38 +3437,38 @@ track_regs () if (ii.get_src_autoinc ()) { int regno = ii.get_src_mem_regno (); - values[regno] = INVALID; + values[regno] = 0; for (std::multimap::iterator j = r2r.find (regno), k = j; j != r2r.end () && j->first == k->first;) { - values[j->second] = INVALID; + values[j->second] = 0; r2r.erase (j++); } } if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ())) - src = INVALID; + src = 0; else { src = SET_SRC(set); if (ii.is_src_mem () && src->volatil) - src = INVALID; + src = 0; } if (ii.get_dst_autoinc ()) { int regno = ii.get_dst_mem_regno (); - values[regno] = INVALID; + values[regno] = 0; for (std::multimap::iterator j = r2r.find (regno), k = j; j != r2r.end () && j->first == k->first;) { - values[j->second] = INVALID; + values[j->second] = 0; r2r.erase (j++); } } - if (src == INVALID || ii.get_src_op () || ii.get_dst_autoinc ()) - dest = INVALID; + if (src == 0 || ii.get_src_op () || ii.get_dst_autoinc ()) + dest = 0; else dest = SET_DEST(set); @@ -3460,19 +3486,20 @@ track_regs () if (sregno >= 0) { values[sregno] = dest; + track->set_version (sregno, version); for (unsigned i = sregno + 1; i < END_REGNO (ii.get_src_reg ()); ++i) - values[i] = INVALID; + values[i] = 0; } if (dregno >= 0) { - // TODO: check for volatile sources values[dregno] = src; + track->set_version (dregno, version); for (unsigned i = dregno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) - values[i] = INVALID; - + values[i] = 0; } } + delete track; } return 0; } @@ -3504,21 +3531,20 @@ opt_elim_dead_assign (void) ++change_count; continue; } - if (ii.get_src_op () == 0) + if (ii.get_src_op () == 0 && ii.get_dst_reg ()) { - rtx cached_value = ii.get_value_for (ii.get_dst_regno ()); + rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; rtx cached_value2 = 0; - if (cached_value && cached_value != INVALID && REG_P(cached_value) && REGNO(cached_value) < 16) - cached_value2 = ii.get_value_for (REGNO(cached_value)); - if (cached_value && cached_value != INVALID + if (cached_value && REG_P(cached_value) && REGNO(cached_value) < FIRST_PSEUDO_REGISTER) + cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)]; + if (cached_value && (rtx_equal_p (cached_value, SET_SRC(set)) - || (cached_value2 && cached_value2 != INVALID && rtx_equal_p (cached_value2, SET_SRC(set))))) + || (cached_value2 && rtx_equal_p (cached_value2, SET_SRC(set))))) { log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); SET_INSN_DELETED(insn); ++change_count; continue; - } } } From eaecabb03f08d5c95aea084f47753a8249c9170a Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 7 Jun 2017 13:03:52 +0200 Subject: [PATCH 163/303] @B enable eliminate dead assignments again, @B fix sp shrinking, @B disable stack frame removal for eh handlers --- gcc/bbb-opts.c | 71 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 6fc53c674a4d..4f14d0799ac4 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1505,21 +1505,29 @@ update_insn_infos (void) if (LABEL_P(insn)) { /* work on all jumps referring to that label. */ - for (l2j_iterator i = label2jump.find (insn->u2.insn_uid), k = i; - i != label2jump.end () && i->first == k->first; ++i) - { - i2i_iterator j = insn2info.find (i->second); - if (j != insn2info.end ()) - { - unsigned index = j->second->get_index (); - insn_info & jj = infos[index]; - if (!jj.is_visited () || !jj.contains (ii)) - { - jj.updateWith (ii); - todo.insert (index); - } - } - } + l2j_iterator i = label2jump.find (insn->u2.insn_uid); + + /* no jump to here -> mark all registers as hard regs. + * This label is maybe used in an exception handler. + * Marking as hard also avoids stack frame removal. + */ + if (i == label2jump.end ()) + infos[pos + 1].make_hard (); + else + for (l2j_iterator k = i; i != label2jump.end () && i->first == k->first; ++i) + { + i2i_iterator j = insn2info.find (i->second); + if (j != insn2info.end ()) + { + unsigned index = j->second->get_index (); + insn_info & jj = infos[index]; + if (!jj.is_visited () || !jj.contains (ii)) + { + jj.updateWith (ii); + todo.insert (index); + } + } + } if (pos == start) pp.mark_visited (); @@ -3128,7 +3136,7 @@ opt_shrink_stack_frame (void) } else { - rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1)); + rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ())); rtx plus; int x = 0; @@ -3137,7 +3145,7 @@ opt_shrink_stack_frame (void) unsigned l = 0; /* no add if a5 is used with pop */ - if (!usea5 || i < prologueend) + if (add1) { plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus); @@ -3180,12 +3188,18 @@ opt_shrink_stack_frame (void) } } - for (unsigned k = 0; k < clobbers.size (); ++k) + for (unsigned k = 0; k < clobbers.size (); ++k, ++l) { rtx clobber = clobbers[k]; - XVECEXP(parallel, 0, l++) = clobber; + XVECEXP(parallel, 0, l) = clobber; } - emit_insn_after (parallel, insn); + + rtx_insn * neu; + if (i < prologueend) + neu = emit_insn_after (parallel, insn); + else + neu = emit_insn_before (parallel, insn); + ii.set_insn (neu); } SET_INSN_DELETED(insn); changed = 1; @@ -3517,20 +3531,21 @@ opt_elim_dead_assign (void) for (int index = infos.size () - 1; index >= 0; --index) { insn_info & ii = infos[index]; - if (!ii.get_dst_reg () || ii.is_compare ()) + if (ii.in_proepi () || !ii.get_dst_reg () || ii.is_compare ()) continue; rtx_insn * insn = ii.get_insn (); rtx set = single_set (insn); if (!set) + continue; - if (ii.get_src_reg () && is_reg_dead (ii.get_dst_regno (), index)) - { - log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]); - SET_INSN_DELETED(insn); - ++change_count; - continue; - } + if (ii.get_dst_reg () && is_reg_dead (ii.get_dst_regno (), index)) + { + log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; + } if (ii.get_src_op () == 0 && ii.get_dst_reg ()) { rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; From 9dad7c865fe3b09382759e1b35f29d577948f88d Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 8 Jun 2017 15:05:24 +0200 Subject: [PATCH 164/303] @B added a workaround for shared CLOBBERS (argh\!), @B mark sp as used in epilogue to avoid elimination of sp corrections, @B defs with mode size < 4 are now always an use too --- gcc/bbb-opts.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 4f14d0799ac4..9825b55a1ea7 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1121,7 +1121,15 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr } else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) - temp_reg_rename (loc, XVECEXP(x, i, j), oldregno, newregno); + { + rtx z = XVECEXP(x, i, j); + if (GET_CODE(z) == CLOBBER) + { + /* workaround for shared clobbers. */ + XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0)); + } + temp_reg_rename (loc, z, oldregno, newregno); + } } } @@ -1484,6 +1492,10 @@ update_insn_infos (void) enum proepis proepi = ii.in_proepi (); + // mark sp reg as used. + if (proepi >= IN_EPILOGUE) + ii.mark_use (STACK_POINTER_REGNUM), infos[start].mark_use (STACK_POINTER_REGNUM); + for (int pos = start; pos >= 0; --pos) { insn_info & pp = infos[pos]; @@ -1578,6 +1590,10 @@ update_insn_infos (void) NOTICE_UPDATE_CC(PATTERN (insn), insn); if (cc_status.value1 || cc_status.value2) use.mark_def (FIRST_PSEUDO_REGISTER); + + // also check mode size if < 4, it's also a def. + if (ii.get_dst_reg () && GET_MODE_SIZE(ii.get_mode()) < 4) + use.mark_def (ii.get_dst_regno ()); } /* mark not renameable in prologue/epilogue. */ @@ -3696,7 +3712,8 @@ opt_absolute (void) { unsigned regno = bit2regno (freemask); if (with_symbol) - log ("(b) modifying %d symbol addresses using %s\n", found.size (), reg_names[regno]); + log ("(b) modifying %d symbol addresses for %s using %s\n", found.size (), + with_symbol->u.block_sym.fld[0].rt_str, reg_names[regno]); else log ("(b) modifying %d absolute addresses using %s\n", found.size (), reg_names[regno]); @@ -3843,10 +3860,10 @@ namespace if (do_merge_add && opt_merge_add ()) done = 0; - if (do_elim_dead_assign && opt_elim_dead_assign ()) + if (do_absolute && opt_absolute ()) done = 0, update_insns (); - if (do_absolute && opt_absolute ()) + if (do_elim_dead_assign && opt_elim_dead_assign ()) done = 0, update_insns (); if (do_bb_reg_rename) From b6bf8403f6febb237c2ae37474c97bb989c40f60 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 9 Jun 2017 13:41:35 +0200 Subject: [PATCH 165/303] @B mark all returns and jumps (in calls) sp using, @B keep volatile flag in absolute_base conversion --- gcc/bbb-opts.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9825b55a1ea7..c8d29013f981 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1291,7 +1291,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) rtx set = single_set (get_insn ()); rtx src = SET_SRC(set); rtx dst = SET_DEST(set); - + bool vola = src->volatil; rtx pattern; rtx reg = gen_raw_REG (SImode, regno); @@ -1348,6 +1348,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) } pattern = gen_rtx_SET(dst, src); + src->volatil = vola; SET_INSN_DELETED(insn); insn = emit_insn_after (pattern, insn); @@ -1661,6 +1662,9 @@ update_insns () { if (inproepilogue || ANY_RETURN_P(PATTERN (insn))) { + if (ANY_RETURN_P(PATTERN (insn))) + ii.set_proepi(IN_EPILOGUE); + scan_starts.insert (infos.size () - 1); inproepilogue = IN_CODE; rtx set = single_set (insn); @@ -1696,6 +1700,7 @@ update_insns () { rtx label = XEXP(ref, 0); label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); + ii.set_proepi(IN_EPILOGUE); } } } @@ -1735,6 +1740,8 @@ update_insns () } else if (CALL_P(insn)) { + if (insn->jump) + ii.set_proepi(IN_EPILOGUE); ii.mark_call (); if (inproepilogue) { From d8619150fdaca31cc31de96fe94f4e4bd212fe76 Mon Sep 17 00:00:00 2001 From: fautomat Date: Fri, 9 Jun 2017 15:00:32 +0100 Subject: [PATCH 166/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index cb00f5c9a36e..ba919c60d861 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170605-091011 +20170609-145423 From d485949ff4cc8d323dbf9b4810fd379ccbe98cfc Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 11 Jun 2017 13:04:22 +0200 Subject: [PATCH 167/303] @R excluded fpgnulib.c from libgcc --- libgcc/config.host | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libgcc/config.host b/libgcc/config.host index f456ff689ad9..1478faa2b027 100644 --- libgcc/config.host +++ libgcc/config.host @@ -817,8 +817,7 @@ m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; m68k-*-amiga*) - tmake_file="$tmake_file -# m68k/t-floatlib" +# tmake_file="$tmake_file m68k/t-floatlib" ;; m68k-*-elf* | fido-*-elf) tmake_file="$tmake_file m68k/t-floatlib" From 4ed9bba08719add41aec99292e4dc315699f6111 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 11 Jun 2017 12:06:59 +0100 Subject: [PATCH 168/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ba919c60d861..e7d6b1e3aa50 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170609-145423 +20170611-120626 From cd1e07319580d7ea753d8202fe8a03aec19a9b3b Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 11 Jun 2017 22:40:39 +0200 Subject: [PATCH 169/303] @B fix linking add -lstubs again --- gcc/config/m68k/m68kamigaos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 8a25f8cbfdfb..50859a4c283f 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -487,7 +487,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #define LIBGCC_IXEMUL_SPEC "" #define LIBGCC_LIBNIX_SPEC "-lnix -fl libnix " \ "%{mcrt=*:-l%*} " \ - "%{!mcrt=*:-lnix20}" + "%{!mcrt=*:-lnix20} -lstubs" #define LIBGCC_CLIB2_SPEC "-lc" #define LIBGCC_SPEC "-lgcc " \ "%{noixemul:%(libgcc_libnix)} " \ From 40fa6300271e5cd3d886f54d5696c6e748ecdc52 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 11 Jun 2017 22:41:23 +0200 Subject: [PATCH 170/303] @B lock a4 if baserel, @B better invalidation in register tracking --- gcc/bbb-opts.c | 168 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 70 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index c8d29013f981..9a0a3ac80e43 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1126,7 +1126,7 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr if (GET_CODE(z) == CLOBBER) { /* workaround for shared clobbers. */ - XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0)); + XVECEXP(x, i, j) = z = gen_rtx_CLOBBER (GET_MODE(z), XEXP(z, 0)); } temp_reg_rename (loc, z, oldregno, newregno); } @@ -1268,7 +1268,7 @@ insn_info::a5_to_a7 (rtx a7) rtx set = single_set (insn); if (set) { - SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC(SImode, a7)); + SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC (SImode, a7)); return; } } @@ -1304,7 +1304,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) if (base == addr) dst = gen_rtx_MEM (mode, reg); else - dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + dst = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset))); dst_mem_reg = reg; dst_mem = true; @@ -1322,13 +1322,13 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) if (base == addr) src = gen_rtx_MEM (mode, reg); else - src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + src = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset))); /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */ if (src_op) { if (src_ee) - src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval)); + src = gen_rtx_fmt_ee (src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval)); else { if (src_op == SIGN_EXTEND) @@ -1336,7 +1336,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) PUT_MODE_RAW(src, mode == SImode ? HImode : mode == HImode ? QImode : SImode); src->call = 1; } - src = gen_rtx_fmt_e(src_op, mode, src); + src = gen_rtx_fmt_e (src_op, mode, src); } } @@ -1347,7 +1347,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) } } - pattern = gen_rtx_SET(dst, src); + pattern = gen_rtx_SET (dst, src); src->volatil = vola; SET_INSN_DELETED(insn); @@ -1485,6 +1485,8 @@ update_insn_infos (void) if (todo.begin () == todo.end ()) todo.insert (infos.size () - 1); + bool locka4 = flag_pic >= 3; + while (!todo.empty ()) { int start = *todo.begin (); @@ -1563,6 +1565,8 @@ update_insn_infos (void) rtx pattern = PATTERN (insn); insn_info use (insn); use.scan (); + if (locka4 && (use.get_myuse () & (1 << PIC_REG))) + use.mark_hard (PIC_REG); /* do not mark a node as visited, if it's in epilogue and not yet visited. */ if (CALL_P(insn) || JUMP_P(insn)) @@ -1663,7 +1667,7 @@ update_insns () if (inproepilogue || ANY_RETURN_P(PATTERN (insn))) { if (ANY_RETURN_P(PATTERN (insn))) - ii.set_proepi(IN_EPILOGUE); + ii.set_proepi (IN_EPILOGUE); scan_starts.insert (infos.size () - 1); inproepilogue = IN_CODE; @@ -1700,7 +1704,7 @@ update_insns () { rtx label = XEXP(ref, 0); label2jump.insert (std::make_pair (label->u2.insn_uid, insn)); - ii.set_proepi(IN_EPILOGUE); + ii.set_proepi (IN_EPILOGUE); } } } @@ -1741,7 +1745,7 @@ update_insns () else if (CALL_P(insn)) { if (insn->jump) - ii.set_proepi(IN_EPILOGUE); + ii.set_proepi (IN_EPILOGUE); ii.mark_call (); if (inproepilogue) { @@ -1860,6 +1864,11 @@ opt_reg_rename (void) /* get the mask for free registers. */ unsigned mask = ii.get_free_mask (); + + /* do not use a4 if compiling baserel */ + if (flag_pic >= 3) + mask &= ~(1 << PIC_REG); + if (!mask) continue; @@ -2300,8 +2309,8 @@ opt_propagate_moves () for (unsigned k = 0; k < jump_out.size (); ++k) { - rtx neu = gen_rtx_SET( - dstj, gen_rtx_PLUS(Pmode, dsti, gen_rtx_CONST_INT(Pmode, fixups[k]))); + rtx neu = gen_rtx_SET ( + dstj, gen_rtx_PLUS (Pmode, dsti, gen_rtx_CONST_INT (Pmode, fixups[k]))); emit_insn_after (neu, jump_out[k]); } } @@ -2377,7 +2386,7 @@ opt_strcpy () int num_clobbers_to_add = 0; int insn_code_number; - rtx pattern = gen_rtx_SET(SET_DEST(single_set(reg2x)), SET_SRC(single_set (x2reg))); + rtx pattern = gen_rtx_SET (SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg))); rtx_insn * newinsn = make_insn_raw (pattern); insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add); if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn))) @@ -2489,10 +2498,10 @@ opt_commute_add_move (void) if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src)) continue; - rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst); + rtx pinc = gen_rtx_POST_INC (GET_MODE(dst), reg1dst); rtx newmem = replace_equiv_address_nv (dst, pinc); - rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src)); + rtx_insn * newinsn = make_insn_raw (gen_rtx_SET (reg1dst, reg1src)); if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn))) continue; @@ -2620,9 +2629,9 @@ opt_const_cmp_to_sub (void) { rtx copyreg = copy_reg (i1.get_dst_reg (), -1); /* create the sub statement. */ - rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval)); + rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval)); - rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub)); + rtx_insn * subinsn = make_insn_raw (gen_rtx_SET (copyreg, sub)); int num_clobbers_to_add = 0; int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add); @@ -2639,8 +2648,8 @@ opt_const_cmp_to_sub (void) subinsn = emit_insn_before (PATTERN (subinsn), i1.get_insn ()); i1.set_insn (subinsn); - rtx neu = gen_rtx_SET(cc0_rtx, - gen_rtx_COMPARE(i1.get_mode (), copyreg, gen_rtx_CONST_INT(i1.get_mode (), 0))); + rtx neu = gen_rtx_SET (cc0_rtx, + gen_rtx_COMPARE (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), 0))); emit_insn_before (neu, i2.get_insn ()); @@ -2661,8 +2670,8 @@ opt_const_cmp_to_sub (void) /* still a compare with 0 -> insert the sub. */ rtx copyreg = copy_reg (i1.get_dst_reg (), -1); /* create the sub statement. */ - rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, c); - rtx set = gen_rtx_SET(copyreg, sub); + rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, c); + rtx set = gen_rtx_SET (copyreg, sub); emit_insn_before (set, pp.get_insn ()); } else @@ -2734,7 +2743,7 @@ opt_merge_add (void) rtx set = PATTERN (insn0); // convert lea (-1,a0),a1 into move.l a0,a1 - rtx_insn * newins0 = make_insn_raw (gen_rtx_SET(XEXP(set, 0), XEXP(XEXP(set, 1), 0))); + rtx_insn * newins0 = make_insn_raw (gen_rtx_SET (XEXP(set, 0), XEXP(XEXP(set, 1), 0))); add_insn_after (newins0, insn0, 0); SET_INSN_DELETED(insn0); // update infos accordingly @@ -3142,24 +3151,24 @@ opt_shrink_stack_frame (void) if (i < prologueend) { /* push */ - rtx dec = gen_rtx_PRE_DEC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); + rtx dec = gen_rtx_PRE_DEC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec); - rtx set = gen_rtx_SET(mem, reg); + rtx set = gen_rtx_SET (mem, reg); emit_insn_after (set, insn); } else { /* pop */ - rtx dec = gen_rtx_POST_INC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); + rtx dec = gen_rtx_POST_INC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec); - rtx set = gen_rtx_SET(reg, mem); + rtx set = gen_rtx_SET (reg, mem); emit_insn_before (set, insn); } } } else { - rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ())); + rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ())); rtx plus; int x = 0; @@ -3170,8 +3179,8 @@ opt_shrink_stack_frame (void) /* no add if a5 is used with pop */ if (add1) { - plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); - XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus); + plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); + XVECEXP(parallel, 0, l) = gen_rtx_SET (a7, plus); ++l; } @@ -3183,10 +3192,10 @@ opt_shrink_stack_frame (void) if (i < prologueend) { /* push */ - plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x)); + plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -x)); x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); - rtx set = gen_rtx_SET(mem, regs[k]); + rtx set = gen_rtx_SET (mem, regs[k]); XVECEXP(parallel, 0, l) = set; } else @@ -3195,17 +3204,17 @@ opt_shrink_stack_frame (void) if (usea5) { x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; - plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); + plus = gen_rtx_PLUS (SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); - rtx set = gen_rtx_SET(regs[k], mem); + rtx set = gen_rtx_SET (regs[k], mem); XVECEXP(parallel, 0, l) = set; } else { - plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; + plus = x ? gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); - rtx set = gen_rtx_SET(regs[k], mem); + rtx set = gen_rtx_SET (regs[k], mem); XVECEXP(parallel, 0, l) = set; } } @@ -3297,8 +3306,8 @@ opt_shrink_stack_frame (void) if (ii.in_proepi () >= IN_EPILOGUE && ii.get_sp_offset () != 0) { log ("(f) adjusting exit sp\n"); - rtx pattern = gen_rtx_SET(a7, - gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT(SImode, - ii.get_sp_offset()))); + rtx pattern = gen_rtx_SET ( + a7, gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -ii.get_sp_offset ()))); emit_insn_before (pattern, ii.get_insn ()); } } @@ -3316,7 +3325,7 @@ opt_shrink_stack_frame (void) rtx pattern = PATTERN (ii.get_insn ()); unsigned sz = XVECLEN(pattern, 0); - rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (sz + 1)); + rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sz + 1)); unsigned n = 0; for (unsigned j = 0; j < sz; ++j) { @@ -3338,8 +3347,8 @@ opt_shrink_stack_frame (void) rtx a = copy_reg (a7, -1); a->frame_related = 1; - rtx plus = gen_rtx_PLUS(SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size)); - rtx set = gen_rtx_SET(a, plus); + rtx plus = gen_rtx_PLUS (SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size)); + rtx set = gen_rtx_SET (a, plus); XVECEXP(parallel, 0, 0) = set; SET_INSN_DELETED(ii.get_insn ()); ii.set_insn (emit_insn_after (parallel, ii.get_insn ())); @@ -3382,12 +3391,18 @@ track_regs () todo.erase (todo.begin ()); rtx * values = track->get_values (); - // track register aliases: know which register refers to this slot - // if a register changes, invalidate each referrer - std::multimap r2r; - for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - if (values[i] && REG_P(values[i])) - r2r.insert (std::make_pair (REGNO(values[i]), i)); + // track register aliases: know which register is used in what slot + // if a register changes, invalidate each slot + std::multimap reg2slot; + for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot) + if (values[slot]) + { + insn_info vv; + vv.scan_rtx (values[slot]); + for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1) + if (m & 1) + reg2slot.insert (std::make_pair (regno, slot)); + } unsigned version = startpos; @@ -3406,10 +3421,16 @@ track_regs () if (ii.is_visited ()) { ii.get_track_var ()->merge (track); - r2r.clear (); - for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - if (values[i] && REG_P(values[i])) - r2r.insert (std::make_pair (REGNO(values[i]), i)); + reg2slot.clear (); + for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot) + if (values[slot]) + { + insn_info vv; + vv.scan_rtx (values[slot]); + for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1) + if (m & 1) + reg2slot.insert (std::make_pair (regno, slot)); + } } else { @@ -3429,16 +3450,16 @@ track_regs () unsigned def = ii.get_def (); if (def) { - for (int i = 0; i < 16; ++i) - if ((1 << i) & def) + for (int regno = 0; regno < 16; ++regno) + if ((1 << regno) & def) { - values[i] = 0; + values[regno] = 0; // invalidate all referring registers - for (std::multimap::iterator j = r2r.find (i), k = j; - j != r2r.end () && j->first == k->first;) + for (std::multimap::iterator j = reg2slot.find (regno), k = j; + j != reg2slot.end () && j->first == k->first;) { values[j->second] = 0; - r2r.erase (j++); + reg2slot.erase (j++); } } } @@ -3475,11 +3496,11 @@ track_regs () { int regno = ii.get_src_mem_regno (); values[regno] = 0; - for (std::multimap::iterator j = r2r.find (regno), k = j; - j != r2r.end () && j->first == k->first;) + for (std::multimap::iterator j = reg2slot.find (regno), k = j; + j != reg2slot.end () && j->first == k->first;) { values[j->second] = 0; - r2r.erase (j++); + reg2slot.erase (j++); } } @@ -3496,11 +3517,11 @@ track_regs () { int regno = ii.get_dst_mem_regno (); values[regno] = 0; - for (std::multimap::iterator j = r2r.find (regno), k = j; - j != r2r.end () && j->first == k->first;) + for (std::multimap::iterator j = reg2slot.find (regno), k = j; + j != reg2slot.end () && j->first == k->first;) { values[j->second] = 0; - r2r.erase (j++); + reg2slot.erase (j++); } } @@ -3513,11 +3534,18 @@ track_regs () int dregno = ii.get_dst_regno (); int sregno = ii.get_src_regno (); - // track r2r - if (dregno >= 0 && sregno >= 0) + // track reg2slot + if (dregno >= 0) { - r2r.insert (std::make_pair (dregno, sregno)); - r2r.insert (std::make_pair (sregno, dregno)); + for (unsigned regno = 0, m = ii.get_myuse (); m; ++regno, m >>= 1) + if (m & 1) + reg2slot.insert (std::make_pair (regno, dregno)); + + if (sregno >= 0) + { + reg2slot.insert (std::make_pair (dregno, sregno)); + reg2slot.insert (std::make_pair (sregno, dregno)); + } } if (sregno >= 0) @@ -3738,14 +3766,14 @@ opt_absolute (void) if (with_symbol) { if (base) - lea = gen_rtx_SET( + lea = gen_rtx_SET ( gen_raw_REG (SImode, regno), - gen_rtx_CONST(SImode, gen_rtx_PLUS(SImode, with_symbol, gen_rtx_CONST_INT (SImode, base)))); + gen_rtx_CONST (SImode, gen_rtx_PLUS (SImode, with_symbol, gen_rtx_CONST_INT (SImode, base)))); else - lea = gen_rtx_SET(gen_raw_REG (SImode, regno), with_symbol); + lea = gen_rtx_SET (gen_raw_REG (SImode, regno), with_symbol); } else - lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); + lea = gen_rtx_SET (gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); insn_info nn (insn); nn.set_use (current_use); From 2950e164bd5d21b9654d111811ebb4bf75d9d618 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 11 Jun 2017 21:58:31 +0100 Subject: [PATCH 171/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e7d6b1e3aa50..be3338d16f6c 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170611-120626 +20170611-215803 From 40d1ade0abfaae48c16daacb5baf2a23a56f3473 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 12 Jun 2017 13:14:52 +0200 Subject: [PATCH 172/303] @B fix redundand load elimination: evaluate multiple jumps to the same label correctly --- gcc/bbb-opts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9a0a3ac80e43..41b384b04cc6 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3381,7 +3381,7 @@ track_regs () update_label2jump (); // add entry point - std::map todo; + std::multimap todo; todo.insert (std::make_pair (0, new track_var ())); while (todo.begin () != todo.end ()) @@ -3411,7 +3411,7 @@ track_regs () insn_info & ii = infos[index]; // already visited? - if (ii.is_visited () && ii.get_track_var ()->contains (track)) + if (index != startpos && ii.is_visited () && ii.get_track_var ()->contains (track)) break; // only keep common values at labels From d56d8369cfbc4f2db520ec76ba22479ab637c5bd Mon Sep 17 00:00:00 2001 From: fautomat Date: Mon, 12 Jun 2017 13:45:19 +0100 Subject: [PATCH 173/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index be3338d16f6c..5d6c1ddcaf32 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170611-215803 +20170612-134455 From 356944afa320b13bbe8b650404dfae48880851a7 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 13 Jun 2017 14:32:12 +0200 Subject: [PATCH 174/303] @B fix link order --- gcc/config/m68k/m68kamigaos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 50859a4c283f..beac496ab148 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -462,7 +462,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{!p:%{!pg:-lc -lamiga -lc}} " \ "%{p:-lc_p} %{pg:-lc_p}" #define LIB_LIBNIX_SPEC \ - "-lnixmain -lnix -lstubs " \ + "-lnixmain -lnix " \ "%{mcrt=*:-l%*} " \ "%{!mcrt=*:-lnix20} " \ "-lamiga " \ From 7ec741afa4116beca5641b8f14f26c71c7ceb92d Mon Sep 17 00:00:00 2001 From: fautomat Date: Tue, 13 Jun 2017 16:01:25 +0100 Subject: [PATCH 175/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5d6c1ddcaf32..bbab26fe7028 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170612-134455 +20170613-160057 From 91689b4bf59a1b051b8b137ccaad5df5b6fbae69 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 14 Jun 2017 22:33:56 +0200 Subject: [PATCH 176/303] @N added opt_autoinc - replace offsets with auto incs --- gcc/bbb-opts.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 270 insertions(+), 38 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 41b384b04cc6..23d8fdb582c3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -439,6 +439,18 @@ class insn_info return dst_mem_reg ? REGNO(dst_mem_reg) : -1; } + inline rtx + get_src_mem_reg () const + { + return src_mem_reg; + } + + inline rtx + get_dst_mem_reg () const + { + return dst_mem_reg; + } + inline int get_src_intval () const { @@ -762,6 +774,12 @@ class insn_info void scan_rtx (rtx); + void + make_post_inc (int regno); + + void + auto_inc_fixup (int regno, int size); + /* return bits for alternate free registers. */ unsigned get_free_mask () const @@ -802,6 +820,64 @@ class insn_info a5_to_a7 (rtx a7); }; +void +insn_info::make_post_inc (int regno) +{ + // convert into POST_INC +// debug_rtx (insn); + rtx set = single_set (insn); + rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); + rtx reg = XEXP(mem, 0); + XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg); +// debug_rtx (insn); + + (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode); +} + +void +insn_info::auto_inc_fixup (int regno, int size) +{ +// debug_rtx (insn); + + rtx set = single_set (insn); + + if (is_compare ()) + set = SET_SRC(set); + + // add to register + if (get_src_regno () == regno) + { + rtx src = SET_SRC(set); + if (get_src_intval () == size) + { + src_intval = 0; + src_plus = false; + SET_SRC(set) = XEXP(src, 0); + } + else + XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size); + } + else + { + rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); + // goto mem if there is an op + if (get_src_mem_regno () == regno && src_op) + mem = XEXP(mem, 1); + + rtx plus = XEXP(mem, 0); + if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == size) + { + XEXP(mem, 0) = XEXP(plus, 0); + (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) = 0; + (get_dst_mem_regno () == regno ? dst_plus : src_plus) = false; + } + else + XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), + (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size); + } +// debug_rtx (insn); +} + track_var * insn_info::get_track_var () { @@ -1126,7 +1202,7 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr if (GET_CODE(z) == CLOBBER) { /* workaround for shared clobbers. */ - XVECEXP(x, i, j) = z = gen_rtx_CLOBBER (GET_MODE(z), XEXP(z, 0)); + XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0)); } temp_reg_rename (loc, z, oldregno, newregno); } @@ -1268,7 +1344,7 @@ insn_info::a5_to_a7 (rtx a7) rtx set = single_set (insn); if (set) { - SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC (SImode, a7)); + SET_SRC(set) = gen_rtx_MEM (mode, gen_rtx_POST_INC(SImode, a7)); return; } } @@ -1304,7 +1380,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) if (base == addr) dst = gen_rtx_MEM (mode, reg); else - dst = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); dst_mem_reg = reg; dst_mem = true; @@ -1322,13 +1398,13 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) if (base == addr) src = gen_rtx_MEM (mode, reg); else - src = gen_rtx_MEM (mode, gen_rtx_PLUS (SImode, reg, gen_rtx_CONST_INT (SImode, offset))); + src = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); /* some operation to the same value as dst. eg. eor #5,symbol+8 -> eor #5,8(ax) */ if (src_op) { if (src_ee) - src = gen_rtx_fmt_ee (src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval)); + src = gen_rtx_fmt_ee(src_op, mode, src, gen_rtx_CONST_INT (mode, src_intval)); else { if (src_op == SIGN_EXTEND) @@ -1336,7 +1412,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) PUT_MODE_RAW(src, mode == SImode ? HImode : mode == HImode ? QImode : SImode); src->call = 1; } - src = gen_rtx_fmt_e (src_op, mode, src); + src = gen_rtx_fmt_e(src_op, mode, src); } } @@ -1347,7 +1423,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) } } - pattern = gen_rtx_SET (dst, src); + pattern = gen_rtx_SET(dst, src); src->volatil = vola; SET_INSN_DELETED(insn); @@ -2309,7 +2385,7 @@ opt_propagate_moves () for (unsigned k = 0; k < jump_out.size (); ++k) { - rtx neu = gen_rtx_SET ( + rtx neu = gen_rtx_SET( dstj, gen_rtx_PLUS (Pmode, dsti, gen_rtx_CONST_INT (Pmode, fixups[k]))); emit_insn_after (neu, jump_out[k]); } @@ -2386,7 +2462,7 @@ opt_strcpy () int num_clobbers_to_add = 0; int insn_code_number; - rtx pattern = gen_rtx_SET (SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg))); + rtx pattern = gen_rtx_SET(SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg))); rtx_insn * newinsn = make_insn_raw (pattern); insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add); if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn))) @@ -2498,10 +2574,10 @@ opt_commute_add_move (void) if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src)) continue; - rtx pinc = gen_rtx_POST_INC (GET_MODE(dst), reg1dst); + rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst); rtx newmem = replace_equiv_address_nv (dst, pinc); - rtx_insn * newinsn = make_insn_raw (gen_rtx_SET (reg1dst, reg1src)); + rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src)); if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn))) continue; @@ -2629,9 +2705,9 @@ opt_const_cmp_to_sub (void) { rtx copyreg = copy_reg (i1.get_dst_reg (), -1); /* create the sub statement. */ - rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval)); + rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), intval)); - rtx_insn * subinsn = make_insn_raw (gen_rtx_SET (copyreg, sub)); + rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub)); int num_clobbers_to_add = 0; int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add); @@ -2648,8 +2724,8 @@ opt_const_cmp_to_sub (void) subinsn = emit_insn_before (PATTERN (subinsn), i1.get_insn ()); i1.set_insn (subinsn); - rtx neu = gen_rtx_SET (cc0_rtx, - gen_rtx_COMPARE (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), 0))); + rtx neu = gen_rtx_SET(cc0_rtx, + gen_rtx_COMPARE (i1.get_mode (), copyreg, gen_rtx_CONST_INT (i1.get_mode (), 0))); emit_insn_before (neu, i2.get_insn ()); @@ -2670,8 +2746,8 @@ opt_const_cmp_to_sub (void) /* still a compare with 0 -> insert the sub. */ rtx copyreg = copy_reg (i1.get_dst_reg (), -1); /* create the sub statement. */ - rtx sub = gen_rtx_PLUS (i1.get_mode (), copyreg, c); - rtx set = gen_rtx_SET (copyreg, sub); + rtx sub = gen_rtx_PLUS(i1.get_mode (), copyreg, c); + rtx set = gen_rtx_SET(copyreg, sub); emit_insn_before (set, pp.get_insn ()); } else @@ -2743,7 +2819,7 @@ opt_merge_add (void) rtx set = PATTERN (insn0); // convert lea (-1,a0),a1 into move.l a0,a1 - rtx_insn * newins0 = make_insn_raw (gen_rtx_SET (XEXP(set, 0), XEXP(XEXP(set, 1), 0))); + rtx_insn * newins0 = make_insn_raw (gen_rtx_SET(XEXP(set, 0), XEXP(XEXP(set, 1), 0))); add_insn_after (newins0, insn0, 0); SET_INSN_DELETED(insn0); // update infos accordingly @@ -3151,24 +3227,24 @@ opt_shrink_stack_frame (void) if (i < prologueend) { /* push */ - rtx dec = gen_rtx_PRE_DEC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); + rtx dec = gen_rtx_PRE_DEC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec); - rtx set = gen_rtx_SET (mem, reg); + rtx set = gen_rtx_SET(mem, reg); emit_insn_after (set, insn); } else { /* pop */ - rtx dec = gen_rtx_POST_INC (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); + rtx dec = gen_rtx_POST_INC(REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, a7); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, dec); - rtx set = gen_rtx_SET (reg, mem); + rtx set = gen_rtx_SET(reg, mem); emit_insn_before (set, insn); } } } else { - rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ())); + rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (regs.size () + add1 + clobbers.size ())); rtx plus; int x = 0; @@ -3179,8 +3255,8 @@ opt_shrink_stack_frame (void) /* no add if a5 is used with pop */ if (add1) { - plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); - XVECEXP(parallel, 0, l) = gen_rtx_SET (a7, plus); + plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, i < prologueend ? -x : x)); + XVECEXP(parallel, 0, l) = gen_rtx_SET(a7, plus); ++l; } @@ -3192,10 +3268,10 @@ opt_shrink_stack_frame (void) if (i < prologueend) { /* push */ - plus = gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -x)); + plus = gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, -x)); x -= REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); - rtx set = gen_rtx_SET (mem, regs[k]); + rtx set = gen_rtx_SET(mem, regs[k]); XVECEXP(parallel, 0, l) = set; } else @@ -3204,17 +3280,17 @@ opt_shrink_stack_frame (void) if (usea5) { x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; - plus = gen_rtx_PLUS (SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); + plus = gen_rtx_PLUS(SImode, a5, gen_rtx_CONST_INT (SImode, a5offset + x)); rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); - rtx set = gen_rtx_SET (regs[k], mem); + rtx set = gen_rtx_SET(regs[k], mem); XVECEXP(parallel, 0, l) = set; } else { - plus = x ? gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; + plus = x ? gen_rtx_PLUS(SImode, a7, gen_rtx_CONST_INT (SImode, x)) : a7; x += REGNO(regs[k]) > STACK_POINTER_REGNUM ? 12 : 4; rtx mem = gen_rtx_MEM (REGNO(regs[k]) > STACK_POINTER_REGNUM ? XFmode : SImode, plus); - rtx set = gen_rtx_SET (regs[k], mem); + rtx set = gen_rtx_SET(regs[k], mem); XVECEXP(parallel, 0, l) = set; } } @@ -3306,7 +3382,7 @@ opt_shrink_stack_frame (void) if (ii.in_proepi () >= IN_EPILOGUE && ii.get_sp_offset () != 0) { log ("(f) adjusting exit sp\n"); - rtx pattern = gen_rtx_SET ( + rtx pattern = gen_rtx_SET( a7, gen_rtx_PLUS (SImode, a7, gen_rtx_CONST_INT (SImode, -ii.get_sp_offset ()))); emit_insn_before (pattern, ii.get_insn ()); } @@ -3325,7 +3401,7 @@ opt_shrink_stack_frame (void) rtx pattern = PATTERN (ii.get_insn ()); unsigned sz = XVECLEN(pattern, 0); - rtx parallel = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sz + 1)); + rtx parallel = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (sz + 1)); unsigned n = 0; for (unsigned j = 0; j < sz; ++j) { @@ -3347,8 +3423,8 @@ opt_shrink_stack_frame (void) rtx a = copy_reg (a7, -1); a->frame_related = 1; - rtx plus = gen_rtx_PLUS (SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size)); - rtx set = gen_rtx_SET (a, plus); + rtx plus = gen_rtx_PLUS(SImode, a, gen_rtx_CONST_INT (SImode, regs_total_size)); + rtx set = gen_rtx_SET(a, plus); XVECEXP(parallel, 0, 0) = set; SET_INSN_DELETED(ii.get_insn ()); ii.set_insn (emit_insn_after (parallel, ii.get_insn ())); @@ -3766,14 +3842,14 @@ opt_absolute (void) if (with_symbol) { if (base) - lea = gen_rtx_SET ( + lea = gen_rtx_SET( gen_raw_REG (SImode, regno), gen_rtx_CONST (SImode, gen_rtx_PLUS (SImode, with_symbol, gen_rtx_CONST_INT (SImode, base)))); else - lea = gen_rtx_SET (gen_raw_REG (SImode, regno), with_symbol); + lea = gen_rtx_SET(gen_raw_REG (SImode, regno), with_symbol); } else - lea = gen_rtx_SET (gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); + lea = gen_rtx_SET(gen_raw_REG (SImode, regno), gen_rtx_CONST_INT (SImode, base)); rtx_insn * insn = emit_insn_before (lea, ii.get_insn ()); insn_info nn (insn); nn.set_use (current_use); @@ -3800,6 +3876,158 @@ opt_absolute (void) return change_count; } +/* + * Convert a series of reg with offset ( (ax), 4(ax), 8(ax), ...) into autoincx ( (ax+), (ax+), (ax+), ...) + * + * 1. search a mem(reg) without offset and either src or dst is using that reg + * 2. follow paths until reg is dead + * 3. if there is another mem(reg) with offset check that + * a) offset fits last mode size + * b) all remaining insn using that reg can be updated by + * i) decrement the offset + * ii) decrement the add value + */ +static unsigned +opt_autoinc () +{ + unsigned change_count = 0; + for (unsigned index = 0; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + + if (ii.in_proepi ()) + continue; + + rtx reg = 0; + if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc () + && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + reg = ii.get_src_mem_reg (); + if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () + && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + reg = ii.get_dst_mem_reg (); + if (!reg) + continue; + + int regno = REGNO(reg); + int size = GET_MODE_SIZE(ii.get_mode ()); + if (size > 4) + continue; + +// log ("starting auto_inc search for %s at %d\n", reg_names[regno], index); + + // track all fixups to modify + std::set fixups; + + // all paths to check + std::vector todo; + todo.push_back (index + 1); + + bool match_size = false; + bool ok = true; + std::set visited; + while (ok && todo.size () > 0) + { + unsigned pos = todo[todo.size () - 1]; + todo.pop_back (); + + if (pos == index) + { + ok = false; + break; + } + + if (visited.find (pos) != visited.end ()) + continue; + visited.insert (pos); + + for (; pos < infos.size (); ++pos) + { + insn_info & jj = infos[pos]; + + // run over labels + if (jj.is_label ()) + continue; + + // break if no longer user + if (!jj.is_use (regno)) + break; + + if (jj.in_proepi ()) + { + ok = false; + break; + } + + // break if in epilogue or add all labels + if (jj.is_jump ()) + { + for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first; + ++j) + todo.push_back (j->second); + continue; + } + + // not used directly + if (!jj.is_myuse (regno)) + continue; + + // if reg is src reg, op must be add and addend must be large enough + if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno) + { + if (jj.get_src_intval () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size)) + { + ok = false; + break; + } + + if (jj.get_dst_addr () == size) + match_size = true; + + fixups.insert (pos); + // end chain, if self assign + if (jj.get_dst_regno () == regno) + break; + + continue; + } + + if (jj.get_dst_mem_regno () == regno) + { + if (jj.get_dst_addr () < size) + { + ok = false; + break; + } + if (jj.get_dst_addr () == size) + match_size = true; + fixups.insert (pos); + } + } + } + + if (!ok || !match_size || !fixups.size ()) + continue; + + log ("(i) auto_inc for %s at %d\n", reg_names[regno], index); + + ii.make_post_inc (regno); + + // fix all offsets / adds + for (std::set::iterator k = fixups.begin (); k != fixups.end (); ++k) + { +// log ("(i) fixup at %d\n", *k); + + insn_info & kk = infos[*k]; + + kk.auto_inc_fixup (regno, size); + } + ++change_count; + --index; // rerun insn to check src and dst + } + + return change_count; +} + namespace { @@ -3870,6 +4098,7 @@ namespace bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); + bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); if (be_very_verbose) log ("ENTER\n"); @@ -3901,6 +4130,9 @@ namespace if (do_elim_dead_assign && opt_elim_dead_assign ()) done = 0, update_insns (); + if (do_autoinc && opt_autoinc ()) + done = 0, update_insns (); + if (do_bb_reg_rename) { while (opt_reg_rename ()) From 210ee63e6fd9926deb41a28130f5c1b5e1dde8ba Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 14 Jun 2017 23:40:23 +0200 Subject: [PATCH 177/303] @B handle compare correctly if converting to autoinc --- gcc/bbb-opts.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 23d8fdb582c3..b81c4db7f136 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -825,13 +825,18 @@ insn_info::make_post_inc (int regno) { // convert into POST_INC // debug_rtx (insn); - rtx set = single_set (insn); + rtx set0 = single_set (insn); + rtx set = set0; + SET_INSN_DELETED(insn); + if (is_compare ()) + set = SET_SRC(set); rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); rtx reg = XEXP(mem, 0); XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg); -// debug_rtx (insn); (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode); + insn = emit_insn_after(set0, insn); +// debug_rtx (insn); } void @@ -839,8 +844,9 @@ insn_info::auto_inc_fixup (int regno, int size) { // debug_rtx (insn); - rtx set = single_set (insn); - + rtx set0 = single_set (insn); + rtx set = set0; + SET_INSN_DELETED(insn); if (is_compare ()) set = SET_SRC(set); @@ -875,6 +881,7 @@ insn_info::auto_inc_fixup (int regno, int size) XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size); } + insn = emit_insn_after(set0, insn); // debug_rtx (insn); } From 9253b9cbb4784817cc6a112b4cb672b721ee131e Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 16 Jun 2017 13:05:58 +0200 Subject: [PATCH 178/303] @B mark word/byte defs as use --- gcc/bbb-opts.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index b81c4db7f136..1a5468418601 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -835,7 +835,7 @@ insn_info::make_post_inc (int regno) XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg); (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode); - insn = emit_insn_after(set0, insn); + insn = emit_insn_after (set0, insn); // debug_rtx (insn); } @@ -881,7 +881,7 @@ insn_info::auto_inc_fixup (int regno, int size) XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size); } - insn = emit_insn_after(set0, insn); + insn = emit_insn_after (set0, insn); // debug_rtx (insn); } @@ -1678,14 +1678,14 @@ update_insn_infos (void) NOTICE_UPDATE_CC(PATTERN (insn), insn); if (cc_status.value1 || cc_status.value2) use.mark_def (FIRST_PSEUDO_REGISTER); - - // also check mode size if < 4, it's also a def. - if (ii.get_dst_reg () && GET_MODE_SIZE(ii.get_mode()) < 4) - use.mark_def (ii.get_dst_regno ()); } + // also check mode size if < 4, it's also a use. + if (pp.get_dst_reg () && GET_MODE_SIZE(pp.get_mode()) < 4) + use.mark_use (pp.get_dst_regno ()); + /* mark not renameable in prologue/epilogue. */ - if (infos[pos].in_proepi () != IN_CODE) + if (pp.in_proepi () != IN_CODE) use.make_hard (); ii.merge (use); @@ -3955,7 +3955,7 @@ opt_autoinc () if (jj.is_label ()) continue; - // break if no longer user + // break if no longer used if (!jj.is_use (regno)) break; @@ -3965,7 +3965,7 @@ opt_autoinc () break; } - // break if in epilogue or add all labels + // add all labels if (jj.is_jump ()) { for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first; @@ -3991,24 +3991,24 @@ opt_autoinc () match_size = true; fixups.insert (pos); - // end chain, if self assign - if (jj.get_dst_regno () == regno) - break; - - continue; } - - if (jj.get_dst_mem_regno () == regno) + else if (jj.get_dst_mem_regno () == regno) { if (jj.get_dst_addr () < size) { ok = false; break; } + if (jj.get_dst_addr () == size) match_size = true; + fixups.insert (pos); } + + // done if this is an add + if (ii.is_def (regno)) + break; } } @@ -4023,11 +4023,10 @@ opt_autoinc () for (std::set::iterator k = fixups.begin (); k != fixups.end (); ++k) { // log ("(i) fixup at %d\n", *k); - insn_info & kk = infos[*k]; - kk.auto_inc_fixup (regno, size); } + ++change_count; --index; // rerun insn to check src and dst } From f0beccad3618cddcc3744347b5e000251394e1f4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 16 Jun 2017 21:12:11 +0200 Subject: [PATCH 179/303] @B reg rename backward start search must not run over unconditional jumps --- gcc/bbb-opts.c | 89 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 1a5468418601..f60232116968 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -71,6 +71,8 @@ #include #include +static int xx = 0; + bool be_very_verbose; bool be_verbose; @@ -1487,7 +1489,7 @@ append_reg_usage (FILE * f, rtx_insn * insn) insn_info & ii = *i->second; if (f != stderr) - fprintf (f, "\n\t\t\t\t\t\t|"); + fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ()); fprintf (f, "%c ", ii.is_stack () ? 's' : ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' '); @@ -1680,9 +1682,10 @@ update_insn_infos (void) use.mark_def (FIRST_PSEUDO_REGISTER); } - // also check mode size if < 4, it's also a use. - if (pp.get_dst_reg () && GET_MODE_SIZE(pp.get_mode()) < 4) - use.mark_use (pp.get_dst_regno ()); + // TODO: use 2 bits for data regs, to indicate mode size +// // also check mode size if < 4, it's also a use for data registers. +// if (pp.get_dst_reg () && pp.get_dst_regno () < 8 && GET_MODE_SIZE(pp.get_mode()) < 4) +// use.mark_use (pp.get_dst_regno ()); /* mark not renameable in prologue/epilogue. */ if (pp.in_proepi () != IN_CODE) @@ -1908,12 +1911,17 @@ find_start (std::set & found, unsigned start, unsigned rename_regno) { unsigned startm1 = start - 1; - /* already searched. */ - if (found.find (startm1) != found.end ()) - break; +// /* already searched. */ +// if (found.find (startm1) != found.end ()) +// break; /* do not run over RETURNS */ insn_info & jj = infos[start]; + + /* stop at labels. If a label is a start pos, a search is maybe started again. */ + if (jj.is_label ()) + break; + insn_info & bb = infos[startm1]; if (jj.in_proepi () == IN_CODE && bb.in_proepi () >= IN_EPILOGUE) break; @@ -1933,6 +1941,7 @@ find_start (std::set & found, unsigned start, unsigned rename_regno) static unsigned opt_reg_rename (void) { + update_label2jump (); // dump_insns ("rename", 1); for (unsigned index = 0; index < infos.size (); ++index) { @@ -1988,15 +1997,38 @@ opt_reg_rename (void) { i2i_iterator j = insn2info.find (i->second); if (j == insn2info.end ()) - continue; + { + mask = 0; + break; + } unsigned start = j->second->get_index (); - if (!infos[start].is_use (rename_regno)) + if (found.find (start) != found.end () || !infos[start].is_use (rename_regno)) continue; +// printf ("label %d <- %d jump\n", pos, start); fflush (stdout); + start = find_start (found, start, rename_regno); todo.insert (start); } + + /* if this label is at a start, check if it is reachable from the previous insn, + * and if, check for use then search start. */ + if (pos == runpos && pos > 0) + { + insn_info & bb = infos[pos - 1]; + rtx set = single_set (bb.get_insn ()); + if (ANY_RETURN_P(bb.get_insn ()) + || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE)) + continue; + + if (bb.is_use (rename_regno)) + { + unsigned start = find_start (found, pos - 1, rename_regno); + todo.insert (start); + } + } + continue; } @@ -2035,37 +2067,21 @@ opt_reg_rename (void) /* follow jump and/or next insn. */ if (JUMP_P(insn)) { - i2i_iterator j = insn2info.find ((rtx_insn *) JUMP_LABEL(insn)); - if (j == insn2info.end ()) + for (j2l_iterator i = jump2label.find (pos), k = i; i != jump2label.end () && i->first == k->first; + ++i) { - /* whoops - label not found. */ - mask = 0; - break; - } + unsigned label_index = i->second; - unsigned label_index = j->second->get_index (); - if (found.find (label_index) == found.end ()) - { - /* if the rename_reg is used in the insn before. - * search the start. - */ + /* add the label to the search list. */ insn_info & bb = infos[label_index + 1]; - if (bb.is_use (rename_regno)) + if (found.find (label_index) == found.end () && bb.is_use (rename_regno)) { - unsigned start = find_start (found, label_index, rename_regno); - todo.insert (start); +// printf ("jump %d -> %d label\n", pos, label_index); fflush (stdout); + todo.insert (label_index); } - todo.insert (label_index + 1); - } - rtx jmppattern = PATTERN (insn); - if (GET_CODE(jmppattern) == PARALLEL) - { - /* can't handle yet. Abort renaming. */ - mask = 0; - break; } - - rtx jmpsrc = XEXP(jmppattern, 1); + rtx set = single_set (insn); + rtx jmpsrc = SET_SRC(set); if (!jmpsrc || GET_CODE(jmpsrc) != IF_THEN_ELSE) break; } @@ -4106,6 +4122,11 @@ namespace bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); + ++xx; + printf ("x: %d\n", xx); +// if (xx <= 90 || xx > 93) +// do_bb_reg_rename = false; + if (be_very_verbose) log ("ENTER\n"); From 77e758b888024c9df2267f0e344ff46efa763951 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 16 Jun 2017 21:53:51 +0200 Subject: [PATCH 180/303] @B update jump2label lookup for autoincs --- gcc/bbb-opts.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f60232116968..473dba829926 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3914,6 +3914,9 @@ static unsigned opt_autoinc () { unsigned change_count = 0; + + update_label2jump(); + for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; @@ -4122,10 +4125,10 @@ namespace bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); - ++xx; - printf ("x: %d\n", xx); -// if (xx <= 90 || xx > 93) -// do_bb_reg_rename = false; +// ++xx; +// printf ("x: %d\n", xx); +// if (xx <= 86 || xx > 90) +// do_autoinc = false; if (be_very_verbose) log ("ENTER\n"); From 669a03b0c64ae38eb9e231cabad983fd6e583325 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 16 Jun 2017 22:26:00 +0200 Subject: [PATCH 181/303] @B cancel autoinc attempt if reg is directly used --- gcc/bbb-opts.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 473dba829926..85f1efea09ab 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3915,7 +3915,7 @@ opt_autoinc () { unsigned change_count = 0; - update_label2jump(); + update_label2jump (); for (unsigned index = 0; index < infos.size (); ++index) { @@ -4024,6 +4024,11 @@ opt_autoinc () fixups.insert (pos); } + else + { + ok = false; + break; + } // done if this is an add if (ii.is_def (regno)) @@ -4127,7 +4132,7 @@ namespace // ++xx; // printf ("x: %d\n", xx); -// if (xx <= 86 || xx > 90) +// if (xx <= 48 || xx > 54) // do_autoinc = false; if (be_very_verbose) From 206ae2727760bc76ca01b111f470b1ed70beced8 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 17 Jun 2017 16:11:36 +0200 Subject: [PATCH 182/303] @B autoinc is now checking the jumps to a label for register usage --- gcc/bbb-opts.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 85f1efea09ab..db791406b0fb 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3970,9 +3970,23 @@ opt_autoinc () { insn_info & jj = infos[pos]; - // run over labels + // check all jumps labels for register usage if (jj.is_label ()) - continue; + { + for (l2j_iterator j = label2jump.find (jj.get_insn ()->u2.insn_uid), k = j; + j != label2jump.end () && j->first == k->first; ++j) + { + insn_info * ll = insn2info.find (j->second)->second; + if (ll->is_use (regno)) + { + ok = false; + break; + } + } + if (ok) + continue; + break; + } // break if no longer used if (!jj.is_use (regno)) From bc3028a6f267699e0d6556b310a5cb75c2600e22 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 17 Jun 2017 21:44:32 +0200 Subject: [PATCH 183/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index bbab26fe7028..e3b60659878c 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170613-160057 +20170617-214407 From 98d760a8b0e4aaeccd8a37d6a55d425853628b1a Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 18 Jun 2017 13:09:59 +0200 Subject: [PATCH 184/303] @B fix for some jump insns with parallel rtx (dbcc) --- gcc/bbb-opts.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index db791406b0fb..f66256954f17 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2081,7 +2081,21 @@ opt_reg_rename (void) } } rtx set = single_set (insn); - rtx jmpsrc = SET_SRC(set); + if (!set) + { + // it's a parallel pattern - search the set pc = ... + rtx pat = PATTERN (insn); + for (int j = XVECLEN (pat, 0) - 1; j >= 0; j--) + { + rtx x = XVECEXP(pat, 0, j); + if (XEXP(x, 0) == pc_rtx) + { + set = x; + break; + } + } + } + rtx jmpsrc = set ? SET_SRC(set) : 0; if (!jmpsrc || GET_CODE(jmpsrc) != IF_THEN_ELSE) break; } From 8bfc9663a96e6256cd360ab4355c8b66515f13f1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 18 Jun 2017 13:11:04 +0200 Subject: [PATCH 185/303] @R define _WCHAR_T_ if typedef-ing wchar_t --- gcc/ginclude/stddef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h index d711530d0535..4f08f81a3ae0 100644 --- gcc/ginclude/stddef.h +++ gcc/ginclude/stddef.h @@ -325,6 +325,7 @@ typedef __rune_t rune_t; #define __WCHAR_TYPE__ int #endif #ifndef __cplusplus +#define _WCHAR_T_ int typedef __WCHAR_TYPE__ wchar_t; #endif #endif From 3362e147aee470ae0715005e851264a30634aefc Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 18 Jun 2017 13:11:43 +0200 Subject: [PATCH 186/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e3b60659878c..668d20875bcc 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170617-214407 +20170618-131118 From c57b23b7b2ac0771437f22e7e9ca81ddbe0f04fa Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 20 Jun 2017 19:12:21 +0200 Subject: [PATCH 187/303] @B fix autoinc generation if src op is present --- gcc/bbb-opts.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f66256954f17..074669a4e844 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -833,6 +833,9 @@ insn_info::make_post_inc (int regno) if (is_compare ()) set = SET_SRC(set); rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); + if (src_op && get_src_mem_regno () == regno) + mem = XEXP(mem, 1); + rtx reg = XEXP(mem, 0); XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg); From 85a73d1de786d310f2c9b8fad247f82c1c233e33 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 20 Jun 2017 19:13:37 +0200 Subject: [PATCH 188/303] @V bump version --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 668d20875bcc..2c8dad4e8bed 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170618-131118 +20170620-191317 From 8adf18dc9ae9c93578612b11935146fc572b662e Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 21 Jun 2017 13:34:32 +0200 Subject: [PATCH 189/303] @B fix flow analysis with tail calls converted to jumps --- gcc/bbb-opts.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 074669a4e844..f9e6e4008a44 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1829,12 +1829,15 @@ update_insns () jump_table = 0; ii.set_proepi (inproepilogue = IN_CODE); if (infos.size () > 1) - scan_starts.insert (infos.size () - 1); + scan_starts.insert (infos.size () - 2); } else if (CALL_P(insn)) { - if (insn->jump) + if (insn->jump) { ii.set_proepi (IN_EPILOGUE); + ii.mark_jump(); + scan_starts.insert (infos.size () - 1); + } ii.mark_call (); if (inproepilogue) { From ad1cbe3452a5355dde8947bc91c41145d56c19c2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 21 Jun 2017 13:35:44 +0200 Subject: [PATCH 190/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2c8dad4e8bed..e907b4926b96 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170620-191317 +20170621-133511 From c1fff35716644f7270e12a819bad64a328ce530b Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 21 Jun 2017 19:32:08 +0200 Subject: [PATCH 191/303] @B do not eliminate self updates, e.g. (a0),a0 --- gcc/bbb-opts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f9e6e4008a44..352c14d18c6c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3716,7 +3716,7 @@ opt_elim_dead_assign (void) ++change_count; continue; } - if (ii.get_src_op () == 0 && ii.get_dst_reg ()) + if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use(ii.get_dst_regno())) { rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; rtx cached_value2 = 0; From f573652f798f9ea72796cced3b8044d3dafd7bad Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 22 Jun 2017 15:20:24 +0200 Subject: [PATCH 192/303] @B fix flow analysis, @D V dumps now no index numbers, vV dumps index numbers into asm --- gcc/bbb-opts.c | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 352c14d18c6c..8b49637f6c09 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -73,7 +73,7 @@ static int xx = 0; -bool be_very_verbose; +int be_very_verbose; bool be_verbose; extern struct lang_hooks lang_hooks; @@ -1468,13 +1468,13 @@ is_reg_dead (unsigned regno, unsigned _pos) // skip labels. for (unsigned pos = _pos + 1; pos < infos.size (); ++pos) { - insn_info & ii0 = infos[pos]; + insn_info & ii = infos[pos]; // skip entries without info - if (ii0.is_empty ()) + if (ii.is_empty ()) continue; // not dead if usage is reported in the next statement - return !ii0.is_use (regno) && !ii0.is_hard (regno); + return !ii.is_use (regno) && !ii.is_hard (regno); } return true; } @@ -1492,10 +1492,14 @@ append_reg_usage (FILE * f, rtx_insn * insn) insn_info & ii = *i->second; if (f != stderr) - fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ()); + { + if (be_very_verbose > 1) + fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ()); + else + fprintf (f, "\n\t\t\t\t\t|\t", ii.get_index ()); + } - fprintf (f, "%c ", - ii.is_stack () ? 's' : ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' '); + fprintf (f, "%c ", ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' '); for (int j = 0; j < 8; ++j) if (ii.is_use (j) || ii.is_def (j)) @@ -1829,15 +1833,16 @@ update_insns () jump_table = 0; ii.set_proepi (inproepilogue = IN_CODE); if (infos.size () > 1) - scan_starts.insert (infos.size () - 2); + scan_starts.insert (infos.size () - 1); } else if (CALL_P(insn)) { - if (insn->jump) { - ii.set_proepi (IN_EPILOGUE); - ii.mark_jump(); - scan_starts.insert (infos.size () - 1); - } + if (insn->jump) + { + ii.set_proepi (IN_EPILOGUE); + ii.mark_jump (); + scan_starts.insert (infos.size () - 1); + } ii.mark_call (); if (inproepilogue) { @@ -2114,6 +2119,7 @@ opt_reg_rename (void) int newregno = bit2regno (mask); /* check the renamed insns. */ + std::vector positions; std::vector > locs; std::vector > patch; bool ok = true; @@ -2138,6 +2144,7 @@ opt_reg_rename (void) *j->first = j->second; } + positions.push_back (*i); locs.clear (); } } @@ -2148,6 +2155,14 @@ opt_reg_rename (void) log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], patch.size (), index); + if (be_verbose) + { + for (std::vector::iterator i = positions.begin (); i != positions.end (); ++i) + printf ("%d ", *i); + printf ("\n"); + fflush (stdout); + } + /* apply all changes. */ for (std::vector >::iterator j = patch.begin (); j != patch.end (); ++j) *j->first = j->second; @@ -3716,7 +3731,7 @@ opt_elim_dead_assign (void) ++change_count; continue; } - if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use(ii.get_dst_regno())) + if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use (ii.get_dst_regno ())) { rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; rtx cached_value2 = 0; @@ -4150,8 +4165,12 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { - be_very_verbose = strchr (string_bbb_opts, 'V'); - be_verbose = be_very_verbose || strchr (string_bbb_opts, 'v'); + be_very_verbose = strchr (string_bbb_opts, 'V') != 0; + be_verbose = strchr (string_bbb_opts, 'v') != 0; + if (be_verbose && be_very_verbose) + ++be_very_verbose; + if (be_very_verbose) + be_verbose = true; bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); From acdf0eba2196c10905cc07af78fba0eca5f457ca Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 22 Jun 2017 15:21:40 +0200 Subject: [PATCH 193/303] @B support trap and preserve all registers --- gcc/bbb-opts.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 8b49637f6c09..35ebc7d770e6 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -979,6 +979,13 @@ insn_info::scan_rtx (rtx x) return; } + if (code == TRAP_IF) + { + /* mark all registers used. */ + hard = use = myuse = (1 << FIRST_PSEUDO_REGISTER) - 1; + return; + } + const char *fmt = GET_RTX_FORMAT(code); for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { From dccd1ea371e35241057b86bdf90cf8be60d2083c Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 22 Jun 2017 16:00:20 +0200 Subject: [PATCH 194/303] @V bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e907b4926b96..95b694bea9d1 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170621-133511 +20170622-160003 From 95ee80db20652f6647cf6f30da3c7c74e7160a62 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 22 Jun 2017 16:01:04 +0200 Subject: [PATCH 195/303] @B eliminate sp assignments after stack frame handling is done --- gcc/bbb-opts.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 35ebc7d770e6..f50c8578f923 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3715,7 +3715,7 @@ track_regs () * delete those insns. */ static unsigned -opt_elim_dead_assign (void) +opt_elim_dead_assign (unsigned blocked_regno) { track_regs (); @@ -3731,14 +3731,15 @@ opt_elim_dead_assign (void) if (!set) continue; - if (ii.get_dst_reg () && is_reg_dead (ii.get_dst_regno (), index)) + if (ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index)) { log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]); SET_INSN_DELETED(insn); ++change_count; continue; } - if (ii.get_src_op () == 0 && ii.get_dst_reg () && !ii.is_use (ii.get_dst_regno ())) + if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno + && !ii.is_use (ii.get_dst_regno ())) { rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; rtx cached_value2 = 0; @@ -4222,7 +4223,7 @@ namespace if (do_absolute && opt_absolute ()) done = 0, update_insns (); - if (do_elim_dead_assign && opt_elim_dead_assign ()) + if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM)) done = 0, update_insns (); if (do_autoinc && opt_autoinc ()) @@ -4246,6 +4247,10 @@ namespace if (opt_shrink_stack_frame ()) update_insns (); } + + /* elim stack pointer stuff last. */ + if (do_elim_dead_assign) + opt_elim_dead_assign (FIRST_PSEUDO_REGISTER); } if (r && be_verbose) log ("no bbb optimization code %d\n", r); From 335edd4fe233548c3353bd7e49fd374fefb6b67c Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Jul 2017 09:10:22 +0200 Subject: [PATCH 196/303] @B fixed regrename: start search was not triggered if the assignment is before a label --- gcc/bbb-opts.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f50c8578f923..247fc522aaa2 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1922,17 +1922,13 @@ is_reg_touched_between (unsigned regno, int from, int to) * search backward and find the initial assignment for that regno. */ static unsigned -find_start (std::set & found, unsigned start, unsigned rename_regno) +find_start (unsigned start, unsigned rename_regno) { /* search the start. */ while (start > 0) { unsigned startm1 = start - 1; -// /* already searched. */ -// if (found.find (startm1) != found.end ()) -// break; - /* do not run over RETURNS */ insn_info & jj = infos[start]; @@ -1995,6 +1991,7 @@ opt_reg_rename (void) unsigned runpos = *todo.begin (); todo.erase (todo.begin ()); +// printf ("runpos %d \n", runpos); fflush (stdout); for (unsigned pos = runpos; mask && pos < infos.size (); ++pos) { /* already searched. */ @@ -2020,19 +2017,19 @@ opt_reg_rename (void) break; } - unsigned start = j->second->get_index (); - if (found.find (start) != found.end () || !infos[start].is_use (rename_regno)) + unsigned startat = j->second->get_index (); + if (found.find (startat) != found.end () || !infos[startat].is_use (rename_regno)) continue; -// printf ("label %d <- %d jump\n", pos, start); fflush (stdout); - start = find_start (found, start, rename_regno); + unsigned start = find_start (startat, rename_regno); +// printf ("label %d <- jump %d : start %d\n", pos, startat, start); fflush (stdout); todo.insert (start); } /* if this label is at a start, check if it is reachable from the previous insn, * and if, check for use then search start. */ - if (pos == runpos && pos > 0) + if (pos > 0) { insn_info & bb = infos[pos - 1]; rtx set = single_set (bb.get_insn ()); @@ -2040,10 +2037,13 @@ opt_reg_rename (void) || (set && SET_DEST(set) == pc_rtx && GET_CODE(SET_SRC(set)) != IF_THEN_ELSE)) continue; - if (bb.is_use (rename_regno)) +// printf ("label start check %d use %d\n", pos, bb.is_use (rename_regno) || bb.is_def(rename_regno)); fflush (stdout); + + if (bb.is_use (rename_regno) || bb.is_def(rename_regno)) { - unsigned start = find_start (found, pos - 1, rename_regno); + unsigned start = find_start (pos - 1, rename_regno); todo.insert (start); +// printf ("label %d : start %d \n", pos, start); fflush (stdout); } } @@ -2094,7 +2094,7 @@ opt_reg_rename (void) insn_info & bb = infos[label_index + 1]; if (found.find (label_index) == found.end () && bb.is_use (rename_regno)) { -// printf ("jump %d -> %d label\n", pos, label_index); fflush (stdout); +// printf ("jump %d -> label %d \n", pos, label_index); fflush (stdout); todo.insert (label_index); } } From 5180bf61c8f24d190fe51722d78f69b4fb566065 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 5 Jul 2017 20:20:50 +0200 Subject: [PATCH 197/303] @B add ctype::~ctype() --- libstdc++-v3/config/os/newlib/ctype_configure_char.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc index 903de5625d77..3198a3069fc6 100644 --- libstdc++-v3/config/os/newlib/ctype_configure_char.cc +++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc @@ -65,6 +65,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_narrow_ok = 0; } + ctype::~ctype() + { + } + char ctype::do_toupper(char __c) const { From f088c99da4c5cdb2b86c57475a2fddbb76deba6f Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 6 Jul 2017 23:38:50 +0200 Subject: [PATCH 198/303] @B resolve ctype vtable issue and avoid duplicate definition --- libstdc++-v3/config/os/newlib/ctype_configure_char.cc | 5 +++++ libstdc++-v3/configure.host | 4 ++-- libstdc++-v3/src/c++11/ctype.cc | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc index 3198a3069fc6..5543759efa51 100644 --- libstdc++-v3/config/os/newlib/ctype_configure_char.cc +++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc @@ -65,9 +65,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_narrow_ok = 0; } +#ifdef TARGET_AMIGA ctype::~ctype() { + _S_destroy_c_locale(_M_c_locale_ctype); + if (_M_del) + delete[] this->table(); } +#endif char ctype::do_toupper(char __c) const diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host index 354b1c7ead46..13444bc5a4cf 100644 --- libstdc++-v3/configure.host +++ libstdc++-v3/configure.host @@ -228,8 +228,8 @@ case "${host_os}" in ;; amiga*) os_include_dir="os/newlib" - CXXFLAGS="${CXXFLAGS} -noixemul" - CPPFLAGS="${CPPFLAGS} -noixemul" +# CXXFLAGS="${CXXFLAGS} -noixemul" +# CPPFLAGS="${CPPFLAGS} -noixemul" ;; bsd*) # Plain BSD attempts to share FreeBSD files. diff --git a/libstdc++-v3/src/c++11/ctype.cc b/libstdc++-v3/src/c++11/ctype.cc index fa370681dad5..6867e61e8b7d 100644 --- libstdc++-v3/src/c++11/ctype.cc +++ libstdc++-v3/src/c++11/ctype.cc @@ -51,12 +51,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const size_t ctype::table_size; +#ifndef TARGET_AMIGA +/* moved to ctype_configure_char */ ctype::~ctype() { _S_destroy_c_locale(_M_c_locale_ctype); if (_M_del) delete[] this->table(); } +#endif // Fill in the narrowing cache and flag whether all values are // valid or not. _M_narrow_ok is set to 2 if memcpy can't From c4e78d720943ce032d2ccfff2ceea56164403d29 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 7 Jul 2017 21:57:40 +0200 Subject: [PATCH 199/303] @B restore -noixemul in libstdc++v3 --- gcc/DATESTAMP | 2 +- libstdc++-v3/configure.host | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 95b694bea9d1..58e8c652ab1b 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170622-160003 +20170707-215619 diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host index 13444bc5a4cf..354b1c7ead46 100644 --- libstdc++-v3/configure.host +++ libstdc++-v3/configure.host @@ -228,8 +228,8 @@ case "${host_os}" in ;; amiga*) os_include_dir="os/newlib" -# CXXFLAGS="${CXXFLAGS} -noixemul" -# CPPFLAGS="${CPPFLAGS} -noixemul" + CXXFLAGS="${CXXFLAGS} -noixemul" + CPPFLAGS="${CPPFLAGS} -noixemul" ;; bsd*) # Plain BSD attempts to share FreeBSD files. From 0fe16b4eac1770fc611f217ca4c9aafdb0065f7e Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 7 Jul 2017 23:01:11 +0200 Subject: [PATCH 200/303] @B fix v2 ctype dtor --- libstdc++-v3/config/os/newlib/ctype_configure_char.cc | 2 +- libstdc++-v3/src/c++11/ctype.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/config/os/newlib/ctype_configure_char.cc b/libstdc++-v3/config/os/newlib/ctype_configure_char.cc index 5543759efa51..ed0c757d42f8 100644 --- libstdc++-v3/config/os/newlib/ctype_configure_char.cc +++ libstdc++-v3/config/os/newlib/ctype_configure_char.cc @@ -65,7 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_narrow_ok = 0; } -#ifdef TARGET_AMIGA +#ifdef __AMIGA__ ctype::~ctype() { _S_destroy_c_locale(_M_c_locale_ctype); diff --git a/libstdc++-v3/src/c++11/ctype.cc b/libstdc++-v3/src/c++11/ctype.cc index 6867e61e8b7d..f80e83034255 100644 --- libstdc++-v3/src/c++11/ctype.cc +++ libstdc++-v3/src/c++11/ctype.cc @@ -51,7 +51,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const size_t ctype::table_size; -#ifndef TARGET_AMIGA +#ifndef __AMIGA__ /* moved to ctype_configure_char */ ctype::~ctype() { From 8e243494b547e0452be69f9decc094f5cdf390db Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:26:30 +0200 Subject: [PATCH 201/303] @B fixed opt_const_cmp_to_sub with chained compares: exit labels were not tested. --- gcc/bbb-opts.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 247fc522aaa2..365eec1c7280 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2717,6 +2717,15 @@ opt_const_cmp_to_sub (void) if (pp.get_dst_regno () != i1.get_dst_regno ()) continue; lastsubval = pp.get_src_intval (); + + // but still check for usage after this jump + j2l_iterator l = jump2label.find(index + 2); + if (l == jump2label.end()) + continue; + + insn_info & label = infos[l->second + 1]; + if (label.is_use (i1.get_dst_regno ())) + continue; } else if (!is_reg_dead (i1.get_dst_regno (), index)) continue; @@ -2752,9 +2761,8 @@ opt_const_cmp_to_sub (void) if (!i2.is_jump ()) continue; - rtx_insn * jump = i2.get_insn (); - rtx jmppattern = PATTERN (jump); - if (GET_RTX_LENGTH (GET_CODE(jmppattern)) < 2) + rtx jmppattern = single_set (i2.get_insn ()); + if (!jmppattern) continue; rtx jmpsrc = XEXP(jmppattern, 1); From be3b4203f780465f6221fe829df769638bb989c6 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:27:44 +0200 Subject: [PATCH 202/303] @N create labels and storage needed for exception handling --- gcc/dwarf2out.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 1357bf24a125..566aaaf4e370 100644 --- gcc/dwarf2out.c +++ gcc/dwarf2out.c @@ -469,6 +469,16 @@ switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED) eh_frame_section = ((flags == SECTION_WRITE) ? data_section : readonly_data_section); #endif /* EH_FRAME_SECTION_NAME */ + +#ifdef TARGET_AMIGA + switch_to_section (data_section); + fputs("\t__EH_FRAME_OBJECT__:\n\t.long 0\n\t.long 0\n\t.long 0\n\t.long 0\n\t.long 0\n\t.long 0\n", asm_out_file); + fputs("\t.stabs \"__EH_FRAME_OBJECTS__\",24,0,0,__EH_FRAME_OBJECT__\n", asm_out_file); + + switch_to_section (eh_frame_section); + ASM_OUTPUT_LABEL (asm_out_file, "_EH_FRAME_BEGIN__"); + fputs("\t.stabs \"__EH_FRAME_BEGINS__\",22,0,0,__EH_FRAME_BEGIN__\n", asm_out_file); +#endif } switch_to_section (eh_frame_section); From 7c0d506d800c3a33d3a9f8b7da0a5be3e4a72178 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:30:55 +0200 Subject: [PATCH 203/303] @N create startup code to init exception structures, link some glue code (cxxglue) if g++ is used to init exceptions. --- gcc/cp/g++spec.c | 16 +++++++++++++++- libgcc/config/m68k/cxxglue.c | 22 ++++++++++++++++++++++ libgcc/config/m68k/t-glue | 5 +++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 libgcc/config/m68k/cxxglue.c create mode 100644 libgcc/config/m68k/t-glue diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c index 03cbde090cb3..c6fc90d546d6 100644 --- gcc/cp/g++spec.c +++ gcc/cp/g++spec.c @@ -262,7 +262,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, #endif /* Add one for shared_libgcc or extra static library. */ - num_args = argc + added + need_math + (library > 0) * 4 + 1; + num_args = argc + added + need_math + (library > 0) * 5 + 1; new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args); i = 0; @@ -347,6 +347,20 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, CL_DRIVER, &new_decoded_options[j]); added_libraries++; j++; + +#ifdef TARGET_AMIGA + { + extern const char * + amiga_m68k_prefix_func (int argc, const char ** argv); + char const * cxxglue = "../lib/gcc/m68k-amigaos/" + DEFAULT_TARGET_VERSION + "/cxxglue.o"; + char const * p = amiga_m68k_prefix_func (1, &cxxglue); + generate_option_input_file (p, &new_decoded_options[j]); + ++j; + } +#endif + /* Add target-dependent static library, if necessary. */ if ((static_link || library > 1) && LIBSTDCXX_STATIC != NULL) { diff --git a/libgcc/config/m68k/cxxglue.c b/libgcc/config/m68k/cxxglue.c new file mode 100644 index 000000000000..2a4e6374d088 --- /dev/null +++ libgcc/config/m68k/cxxglue.c @@ -0,0 +1,22 @@ +#include "stabs.h" + +extern void __register_frame_info(void *, void *); +extern void * _EH_FRAME_BEGINS__; +extern void * _EH_FRAME_OBJECTS__; + +void __init_eh() { + void ** frame = &_EH_FRAME_BEGINS__; + void ** object = &_EH_FRAME_OBJECTS__; + + int n = *(int *)frame++; + int m = *(int *)object++; + if (n != m) + return; + + while (n--) { + __register_frame_info(*frame++, *object++); + } +} + +ADD2INIT(__init_eh,127); + diff --git a/libgcc/config/m68k/t-glue b/libgcc/config/m68k/t-glue new file mode 100644 index 000000000000..e65335f2e5f7 --- /dev/null +++ libgcc/config/m68k/t-glue @@ -0,0 +1,5 @@ +cxxglue.o: $(srcdir)/config/m68k/cxxglue.c + $(CC) $(CFLAGS) -c $< + +EXTRA_PARTS=cxxglue.o + From 54f7a6eb27c74a7f4358a32c4f018ca12512bab0 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:38:25 +0200 Subject: [PATCH 204/303] @R do not add cxxglue if -fno-exceptions is specified --- gcc/cp/g++spec.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c index c6fc90d546d6..0bc7d4f78018 100644 --- gcc/cp/g++spec.c +++ gcc/cp/g++spec.c @@ -350,14 +350,24 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, #ifdef TARGET_AMIGA { - extern const char * - amiga_m68k_prefix_func (int argc, const char ** argv); - char const * cxxglue = "../lib/gcc/m68k-amigaos/" - DEFAULT_TARGET_VERSION - "/cxxglue.o"; - char const * p = amiga_m68k_prefix_func (1, &cxxglue); - generate_option_input_file (p, &new_decoded_options[j]); - ++j; + bool addglue = true; + /* do not add glue if exceptions are disabled. */ + for (int ii = 0; ii < argc; ++ii) + { + if (decoded_options[ii].opt_index == OPT_fexceptions) + addglue = decoded_options[ii].opt_index; + } + if (addglue) + { + extern const char * + amiga_m68k_prefix_func (int argc, const char ** argv); + char const * cxxglue = "../lib/gcc/m68k-amigaos/" + DEFAULT_TARGET_VERSION + "/cxxglue.o"; + char const * p = amiga_m68k_prefix_func (1, &cxxglue); + generate_option_input_file (p, &new_decoded_options[j]); + ++j; + } } #endif From 68afa4d4843d806f89436406aa175babaf951e33 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:42:57 +0200 Subject: [PATCH 205/303] @R enable cxxglue --- libgcc/Makefile.in | 4 ++-- libgcc/config.host | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index f09b39b0e85f..39f91d1567b6 100644 --- libgcc/Makefile.in +++ libgcc/Makefile.in @@ -230,7 +230,7 @@ endif # Options to use when compiling libgcc2.a. # LIBGCC2_DEBUG_CFLAGS = -g -LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ +LIBGCC2_CFLAGS = $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \ -fbuilding-libgcc -fno-stack-protector \ $(INHIBIT_LIBC_CFLAGS) @@ -284,7 +284,7 @@ INTERNAL_CFLAGS = $(CFLAGS) $(LIBGCC2_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ $(INCLUDES) @set_have_cc_tls@ @set_use_emutls@ # Options to use when compiling crtbegin/end. -CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \ +CRTSTUFF_CFLAGS = $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \ $(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \ -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \ -fbuilding-libgcc -fno-stack-protector $(FORCE_EXPLICIT_EH_REGISTRY) \ diff --git a/libgcc/config.host b/libgcc/config.host index 1478faa2b027..0fa6eab77340 100644 --- libgcc/config.host +++ libgcc/config.host @@ -817,7 +817,7 @@ m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; m68k-*-amiga*) -# tmake_file="$tmake_file m68k/t-floatlib" + tmake_file="$tmake_file m68k/t-cxxglue" ;; m68k-*-elf* | fido-*-elf) tmake_file="$tmake_file m68k/t-floatlib" From 3984d072175a725d99fa7fdab7e553f8edf7d413 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:47:04 +0200 Subject: [PATCH 206/303] @R remove some hard coded -O2 flags --- libstdc++-v3/configure.host | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host index 354b1c7ead46..137e15e96d26 100644 --- libstdc++-v3/configure.host +++ libstdc++-v3/configure.host @@ -228,8 +228,7 @@ case "${host_os}" in ;; amiga*) os_include_dir="os/newlib" - CXXFLAGS="${CXXFLAGS} -noixemul" - CPPFLAGS="${CPPFLAGS} -noixemul" + CFLAGS="-Os -noixemul" ;; bsd*) # Plain BSD attempts to share FreeBSD files. From a3f9038954373027f5ff07bf1a694b90dc86bd49 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:47:49 +0200 Subject: [PATCH 207/303] @N hacked the mechanism to restore the registers during excpetion handling --- libgcc/unwind-dw2.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++-- libgcc/unwind.inc | 8 ++--- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index 1fb6026d123f..da6e077b7b3c 100644 --- libgcc/unwind-dw2.c +++ libgcc/unwind-dw2.c @@ -260,6 +260,9 @@ _Unwind_GetCFA (struct _Unwind_Context *context) } /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ +#ifdef TARGET_AMIGA +static int overregs[16]; +#endif inline void _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) @@ -271,6 +274,9 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); size = dwarf_reg_size_table[index]; +#ifdef TARGET_AMIGA + overregs[index] = val; +#endif if (_Unwind_IsExtendedContext (context) && context->by_value[index]) { context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val); @@ -279,6 +285,9 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index]; + if (!ptr) + return; + if (size == sizeof(_Unwind_Ptr)) * (_Unwind_Ptr *) ptr = val; else @@ -1612,10 +1621,10 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), macro because __builtin_eh_return must be invoked in the context of our caller. */ -#define uw_install_context(CURRENT, TARGET) \ +#define uw_install_context(CURRENT, TARGET, INDEX) \ do \ { \ - long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ + long offset = uw_install_context_1 ((CURRENT), (TARGET), (INDEX)); \ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ _Unwind_DebugHook ((TARGET)->cfa, handler); \ __builtin_eh_return (offset, handler); \ @@ -1624,7 +1633,8 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), static long uw_install_context_1 (struct _Unwind_Context *current, - struct _Unwind_Context *target) + struct _Unwind_Context *target, + int index ATTRIBUTE_UNUSED) { long i; _Unwind_SpTmp sp_slot; @@ -1659,7 +1669,76 @@ uw_install_context_1 (struct _Unwind_Context *current, else if (t && c && t != c) memcpy (c, t, dwarf_reg_size_table[i]); } + } +#ifdef __AMIGA__ + /* SBF: evil hack to patch the values for d0/d1 into the stack location. + * search the movem insn and count the saved regs. + * Now patch the values into location. + * Always patch d0/d1 since override is always invoked for d0/d1. + * Then patch all other regs which the above code omitted. + */ + /* uw_install_context_1 is called from 4 different locations - each uses an unique index. + * So initialization is only done once. + */ + static unsigned short counts[4]; + static unsigned short masks[4]; + + unsigned short count = 0; + unsigned short reg_mask = masks[index]; + /* init each index once. */ + if (!reg_mask) + { + /* get the return address.*/ + unsigned short * sp = *(((unsigned short **)¤t) - 1); + /* search the movem -x(a5),regs insn.*/ + for (;;) + { + unsigned short s = *sp++; +// printf("%04x ", s); + gcc_assert(s != (unsigned short)0x4e75);// hit return? ouch! + if (s == (unsigned short)0x4ced) + break; + } + reg_mask = *sp; + /* count saved regs */ + for (unsigned short i = 0, m = reg_mask; i < 16; ++i) + { + if (m & 1) + ++count; + m >>= 1; + } + masks[index] = reg_mask; + counts[index] = count; + } + else + count = counts[index]; + + /* regs are saved below local vars -> start at current */ + int * p = ((int *)current) - count; + + for (unsigned short i = 0, m = reg_mask; i < 16; ++i) + { + if (m & 1) + { + if (i <= 1 || (!current->reg[i] && (target->reg[i] || target->by_value[i]))) + { + int old = *p; + /* not set by the code above - set it here */ + if (i <= 1) // use the override values for d0/d1 + *p = overregs[i]; + else + if (target->by_value[i]) + *p = (int)target->reg[i]; + else + *p = *(int*)target->reg[i]; +// printf("patch reg %d from %08lx to %08lx\n", i, old, *p); + } + ++p; + } + m >>= 1; + } +#endif /* If the current frame doesn't have a saved stack pointer, then we need to rely on EH_RETURN_STACKADJ_RTX to get our target stack pointer value reloaded. */ diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc index 7413b55e3fab..bf07725ac840 100644 --- libgcc/unwind.inc +++ libgcc/unwind.inc @@ -132,7 +132,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) if (code != _URC_INSTALL_CONTEXT) return code; - uw_install_context (&this_context, &cur_context); + uw_install_context (&this_context, &cur_context, 0); } @@ -208,7 +208,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, if (code != _URC_INSTALL_CONTEXT) return code; - uw_install_context (&this_context, &cur_context); + uw_install_context (&this_context, &cur_context, 1); } @@ -233,7 +233,7 @@ _Unwind_Resume (struct _Unwind_Exception *exc) gcc_assert (code == _URC_INSTALL_CONTEXT); - uw_install_context (&this_context, &cur_context); + uw_install_context (&this_context, &cur_context, 2); } @@ -258,7 +258,7 @@ _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc) gcc_assert (code == _URC_INSTALL_CONTEXT); - uw_install_context (&this_context, &cur_context); + uw_install_context (&this_context, &cur_context, 3); } From 1d661106336bf40c63163fcc4e30c9c46b45cf9e Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:48:11 +0200 Subject: [PATCH 208/303] @V bump version --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 58e8c652ab1b..51af5f4da01f 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170707-215619 +20170711-124202 From af2b3738ed3afb31a0c1aed11cdc5e2d9db3a65b Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 11 Jul 2017 12:49:56 +0200 Subject: [PATCH 209/303] @B fix evaluating -fno-exceptions --- gcc/cp/g++spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c index 0bc7d4f78018..83a5ab514c79 100644 --- gcc/cp/g++spec.c +++ gcc/cp/g++spec.c @@ -355,7 +355,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, for (int ii = 0; ii < argc; ++ii) { if (decoded_options[ii].opt_index == OPT_fexceptions) - addglue = decoded_options[ii].opt_index; + addglue = decoded_options[ii].value; } if (addglue) { From 11b4ecb7269e55ca24a184e558883aeb5fe33342 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 12 Jul 2017 07:24:02 +0200 Subject: [PATCH 210/303] @B fix merge ... --- libgcc/unwind-dw2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index da6e077b7b3c..7bf0e4236f64 100644 --- libgcc/unwind-dw2.c +++ libgcc/unwind-dw2.c @@ -1669,7 +1669,6 @@ uw_install_context_1 (struct _Unwind_Context *current, else if (t && c && t != c) memcpy (c, t, dwarf_reg_size_table[i]); } - } #ifdef __AMIGA__ /* SBF: evil hack to patch the values for d0/d1 into the stack location. * search the movem insn and count the saved regs. From c760f9bdfda61e158d5d71b44d9163f7802d0314 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 12 Jul 2017 09:12:56 +0200 Subject: [PATCH 211/303] @B fix libstdc++ config --- libstdc++-v3/configure.host | 1 + 1 file changed, 1 insertion(+) diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host index 137e15e96d26..fde4a72bd31b 100644 --- libstdc++-v3/configure.host +++ libstdc++-v3/configure.host @@ -229,6 +229,7 @@ case "${host_os}" in amiga*) os_include_dir="os/newlib" CFLAGS="-Os -noixemul" + CPPFLAGS="-Os -noixemul" ;; bsd*) # Plain BSD attempts to share FreeBSD files. From bd065307745a5bbf8c56e72d94e291e595103897 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 12 Jul 2017 12:08:05 +0200 Subject: [PATCH 212/303] change host pattern from m68k-*-amiga to m68k*-amiga --- libgcc/config.host | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgcc/config.host b/libgcc/config.host index 0fa6eab77340..8e4fb7942f79 100644 --- libgcc/config.host +++ libgcc/config.host @@ -816,7 +816,7 @@ m32r-*-linux*) m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; -m68k-*-amiga*) +m68k*-amiga*) tmake_file="$tmake_file m68k/t-cxxglue" ;; m68k-*-elf* | fido-*-elf) From 17dc596a0d8a232ae647216f27d707010c3e836e Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 12 Jul 2017 14:07:28 +0200 Subject: [PATCH 213/303] fix t-glue makefile name --- libgcc/config.host | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libgcc/config.host b/libgcc/config.host index 8e4fb7942f79..5de7abdb8a95 100644 --- libgcc/config.host +++ libgcc/config.host @@ -816,8 +816,8 @@ m32r-*-linux*) m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; -m68k*-amiga*) - tmake_file="$tmake_file m68k/t-cxxglue" +m68k-*-amiga*) + tmake_file="$tmake_file m68k/t-glue" ;; m68k-*-elf* | fido-*-elf) tmake_file="$tmake_file m68k/t-floatlib" From cfa7b74b520032da16a32425a6d206cba92d0feb Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 20 Aug 2017 21:40:08 +0200 Subject: [PATCH 214/303] fix #1: fix inc/erase with iterator --- gcc/bbb-opts.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 365eec1c7280..99785cf5d6ad 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3608,7 +3608,7 @@ track_regs () j != reg2slot.end () && j->first == k->first;) { values[j->second] = 0; - reg2slot.erase (j++); + j = reg2slot.erase (j); } } } @@ -3649,7 +3649,7 @@ track_regs () j != reg2slot.end () && j->first == k->first;) { values[j->second] = 0; - reg2slot.erase (j++); + j = reg2slot.erase (j); } } @@ -3670,7 +3670,7 @@ track_regs () j != reg2slot.end () && j->first == k->first;) { values[j->second] = 0; - reg2slot.erase (j++); + j = reg2slot.erase (j); } } @@ -3886,9 +3886,9 @@ opt_absolute (void) bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg () && kk.get_src_symbol () == with_symbol; if (k_dst && kk.get_dst_addr () - base > 0x7ffc) - found.erase (k++); + k = found.erase (k); else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc) - found.erase (k++); + k = found.erase (k); else ++k; } From 13bdc411c4eb3fcec280affc02b38e8e7b29e7d4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 21 Aug 2017 17:49:51 +0200 Subject: [PATCH 215/303] fix printing baserel insns, avoid combines resulting in 'not pic_reg' --- gcc/config/m68k/amigaos.c | 32 ++++++++++++++++++++++++++++++++ gcc/config/m68k/amigaos.h | 5 +++++ gcc/config/m68k/m68k.c | 2 +- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index dc2f2ac74369..6aee22fa3720 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -885,3 +885,35 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED) return 0; } +/* + * decline src like: +(plus:SI (reg/f:SI 0 d0 [210]) + (const:SI (minus:SI (not:SI (reg:SI 12 a4)) + * + */ +bool +amigaos_legitimate_combined_insn (rtx_insn * insn) +{ + rtx set = single_set(insn); + if (!set) + return true; + + rtx x = SET_SRC(set); + if (GET_CODE(x) != PLUS) + return true; + + x = XEXP(x, 1); + if (GET_CODE(x) != CONST) + return true; + + x = XEXP(x, 0); + if (GET_CODE(x) != MINUS) + return true; + + x = XEXP(x, 0); + if (GET_CODE(x) != NOT) + return true; + + x = XEXP(x, 0); + return !REG_P(x); +} diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index c564c3f2db67..688f04e37ebb 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -477,3 +477,8 @@ amigaos_struct_value_rtx(tree fntype, rtx amigaos_static_chain_rtx(const_tree fntype, bool incoming ATTRIBUTE_UNUSED); + +#undef TARGET_LEGITIMATE_COMBINED_INSN +#define TARGET_LEGITIMATE_COMBINED_INSN amigaos_legitimate_combined_insn +bool +amigaos_legitimate_combined_insn (rtx_insn *insn ATTRIBUTE_UNUSED); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index d123cc065c18..ed9b76caf11d 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -4626,7 +4626,7 @@ print_operand (FILE *file, rtx op, int letter) /* Use `print_operand_address' instead of `output_addr_const' to ensure that we print relevant PIC stuff. */ asm_fprintf (file, "%I"); - if (TARGET_PCREL + if ((TARGET_PCREL || flag_pic > 2) && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)) print_operand_address (file, op); else From dd13371d6f4ca2e66804a589b50d2bca47d58653 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 21 Aug 2017 20:27:22 +0200 Subject: [PATCH 216/303] avoid invalid addressing modes with baserel modes --- gcc/config/m68k/m68k.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index d5ab0cfab8c8..c9ea341789f4 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -2468,7 +2468,7 @@ (define_insn "*addsi3_internal" [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,d,a") (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0") - (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))] + (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLt,mSrIKLt")))] "! TARGET_COLDFIRE" From 7edabb7a5a3018fd8b1f410f38a31122cc0ea493 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 21 Aug 2017 20:33:59 +0200 Subject: [PATCH 217/303] bump datestamp --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 51af5f4da01f..d77b05782e7b 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170711-124202 +20170821-203326 From 3142cd34592cdaf86c3fab9de2c674225257df8b Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 31 Aug 2017 16:14:24 +0200 Subject: [PATCH 218/303] #2 treat CLOBBERed regs as defined regs --- gcc/bbb-opts.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 99785cf5d6ad..77537a73a873 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1003,6 +1003,9 @@ insn_info::scan_rtx (rtx x) def |= d; } } + + if (code == CLOBBER) + def |= use; } void From 821e16347528355a29fdcfd521f7cdb26414a67f Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 31 Aug 2017 16:18:10 +0200 Subject: [PATCH 219/303] also use libm020 with mcpu=68030 and higher --- gcc/config/m68k/m68kamigaos.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index beac496ab148..7dc0e57f5cdc 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -540,6 +540,9 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ "%{resident32:-m amiga_bss -amiga-datadata-reloc -fl libb32 %{noixemul:-fl libnix} %{mcrt=nix*:-fl libnix}} " \ "%{g:-amiga-debug-hunk} " \ "%{mcpu=68020:-fl libm020} " \ + "%{mcpu=68030:-fl libm020} " \ + "%{mcpu=68040:-fl libm020} " \ + "%{mcpu=68060:-fl libm020} " \ "%{m68020:-fl libm020} " \ "%{mc68020:-fl libm020} " \ "%{m68030:-fl libm020} " \ From 8529c8e37e017866c4d062006a00219fd4977381 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 31 Aug 2017 16:25:52 +0200 Subject: [PATCH 220/303] bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d77b05782e7b..0dfee2790f53 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170821-203326 +20170831-161819 From 592ee5156864548a6d918a34001781a5a73eb51b Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 11 Oct 2017 23:39:40 +0200 Subject: [PATCH 221/303] split fpgnulib into files per function --- libgcc/config.host | 3 ++- libgcc/config/m68k/fpgnulib.c | 22 +++++++++++++++++ libgcc/config/m68k/t-floatlib | 57 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/libgcc/config.host b/libgcc/config.host index 5de7abdb8a95..c36e829a5025 100644 --- libgcc/config.host +++ libgcc/config.host @@ -817,7 +817,8 @@ m32rle-*-linux*) tmake_file="$tmake_file m32r/t-linux t-fdpbit" ;; m68k-*-amiga*) - tmake_file="$tmake_file m68k/t-glue" + tmake_file="$tmake_file m68k/t-glue m68k/t-floatlib soft-fp" +# tmake_file="$tmake_file m68k/t-glue soft-fp" ;; m68k-*-elf* | fido-*-elf) tmake_file="$tmake_file m68k/t-floatlib" diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c index fe41edf26aa0..9dcd5ea20397 100644 --- libgcc/config/m68k/fpgnulib.c +++ libgcc/config/m68k/fpgnulib.c @@ -105,6 +105,7 @@ union long_double_long #ifndef EXTFLOAT +#ifdef __UNORDSF2 int __unordsf2(float a, float b) { @@ -118,7 +119,9 @@ __unordsf2(float a, float b) return 1; return 0; } +#endif +#ifdef __UNORDDF2 int __unorddf2(double a, double b) { @@ -134,7 +137,9 @@ __unorddf2(double a, double b) return 1; return 0; } +#endif +#ifdef __FLOATUNSIDF /* convert unsigned int to double */ double __floatunsidf (unsigned long a1) @@ -167,7 +172,9 @@ __floatunsidf (unsigned long a1) return dl.d; } +#endif +#ifdef __FLOATSIDF /* convert int to double */ double __floatsidf (long a1) @@ -213,7 +220,9 @@ __floatsidf (long a1) return dl.d; } +#endif +#ifdef __FLOATUNSISF /* convert unsigned int to float */ float __floatunsisf (unsigned long l) @@ -221,7 +230,10 @@ __floatunsisf (unsigned long l) double foo = __floatunsidf (l); return foo; } +#endif + +#ifdef __FLOATSISF /* convert int to float */ float __floatsisf (long l) @@ -229,7 +241,10 @@ __floatsisf (long l) double foo = __floatsidf (l); return foo; } +#endif + +#ifdef __EXTENDSFDF2 /* convert float to double */ double __extendsfdf2 (float a1) @@ -268,7 +283,9 @@ __extendsfdf2 (float a1) return dl.d; } +#endif +#ifdef __TRUNCDFSF2 /* convert double to float */ float __truncdfsf2 (double a1) @@ -336,7 +353,9 @@ __truncdfsf2 (double a1) fl.l = PACK (SIGND (dl1), exp, mant); return (fl.f); } +#endif +#ifdef __FIXDFSI /* convert double to int */ long __fixdfsi (double a1) @@ -368,7 +387,9 @@ __fixdfsi (double a1) return (SIGND (dl1) ? -l : l); } +#endif +#ifdef __FIXSFSI /* convert float to int */ long __fixsfsi (float a1) @@ -376,6 +397,7 @@ __fixsfsi (float a1) double foo = a1; return __fixdfsi (foo); } +#endif #else /* EXTFLOAT */ diff --git a/libgcc/config/m68k/t-floatlib b/libgcc/config/m68k/t-floatlib index 1ee8782d9fd2..42f6cf97ef48 100644 --- libgcc/config/m68k/t-floatlib +++ libgcc/config/m68k/t-floatlib @@ -1,10 +1,55 @@ -LIB1ASMSRC = m68k/lb1sf68.S -LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \ - _double _float _floatex \ - _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \ - _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2 +# +#LIB1ASMSRC = m68k/lb1sf68.S +#LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \ +# _double _float _floatex \ +# _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \ +# _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2 +# -LIB2ADD = $(srcdir)/config/m68k/fpgnulib.c xfgnulib.c +LIB2ADD = xfgnulib.c xfgnulib__unordsf2.c xfgnulib__unorddf2.c \ + xfgnulib__floatunsidf.c xfgnulib__floatsidf.c xfgnulib__floatunsisf.c \ + xfgnulib__floatsisf.c xfgnulib__extendsfdf2.c xfgnulib__truncdfsf2.c \ + xfgnulib__fixdfsi.c xfgnulib__fixsfsi.c + +xfgnulib__unordsf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __UNORDSF2' > xfgnulib__unordsf2.c + cat $< >> xfgnulib__unordsf2.c + +xfgnulib__unorddf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __UNORDDF2' > xfgnulib__unorddf2.c + cat $< >> xfgnulib__unorddf2.c + +xfgnulib__floatunsidf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATUNSIDF' > xfgnulib__floatunsidf.c + cat $< >> xfgnulib__floatunsidf.c + +xfgnulib__floatsidf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATSIDF' > xfgnulib__floatsidf.c + cat $< >> xfgnulib__floatsidf.c + +xfgnulib__floatunsisf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATUNSISF' > xfgnulib__floatunsisf.c + cat $< >> xfgnulib__floatunsisf.c + +xfgnulib__floatsisf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATSISF' > xfgnulib__floatsisf.c + cat $< >> xfgnulib__floatsisf.c + +xfgnulib__extendsfdf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __EXTENDSFDF2' > xfgnulib__extendsfdf2.c + cat $< >> xfgnulib__extendsfdf2.c + +xfgnulib__truncdfsf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __TRUNCDFSF2' > xfgnulib__truncdfsf2.c + cat $< >> xfgnulib__truncdfsf2.c + +xfgnulib__fixdfsi.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FIXDFSI' > xfgnulib__fixdfsi.c + cat $< >> xfgnulib__fixdfsi.c + +xfgnulib__fixsfsi.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FIXSFSI' > xfgnulib__fixsfsi.c + cat $< >> xfgnulib__fixsfsi.c xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c echo '#define EXTFLOAT' > xfgnulib.c From cce4b48ca8802f0c0b1ee929810a845a18285902 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 11 Oct 2017 23:40:39 +0200 Subject: [PATCH 222/303] fix usage of return val registers for library functions -> always tell the return reg. --- gcc/DATESTAMP | 2 +- gcc/bbb-opts.c | 2 +- gcc/config/m68k/amigaos.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 0dfee2790f53..c4335f1aad48 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20170831-161819 +20171011-233828 diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 77537a73a873..fe7cd79b5c7b 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -926,7 +926,7 @@ insn_info::scan () rtx op, reg; if (GET_CODE (op = XEXP (link, 0)) == USE && REG_P(reg = XEXP (op, 0))) - for (unsigned r = REGNO(reg); r <= END_REGNO (reg); ++r) + for (unsigned r = REGNO(reg); r < END_REGNO (reg); ++r) mark_myuse (r); } /* mark scratch registers. */ diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 6aee22fa3720..53e01499341d 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -848,10 +848,10 @@ read_only_operand (rtx operand) rtx amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED) { - if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype)) +// if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype)) return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM); - return 0; +// return 0; } rtx From aea9ac0b4d8f6261006ed68ea1bb21d0f6fe57f8 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 13 Oct 2017 22:02:17 +0200 Subject: [PATCH 223/303] further spltting of fpgnulib --- libgcc/config/m68k/fpgnulib.c | 69 +++++++++++++++------------- libgcc/config/m68k/t-floatlib | 102 ++++++++++++++++++++++-------------------- 2 files changed, 91 insertions(+), 80 deletions(-) diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c index 9dcd5ea20397..90926104d8fd 100644 --- libgcc/config/m68k/fpgnulib.c +++ libgcc/config/m68k/fpgnulib.c @@ -418,6 +418,8 @@ float __truncdfsf2 (double); long __fixdfsi (double); long __fixsfsi (float); +#if !defined(EXTFLOATCMP) + int __unordxf2(long double a, long double b) { @@ -467,38 +469,6 @@ __extenddfxf2 (double d) return ldl.ld; } -/* convert long double to double */ -double -__truncxfdf2 (long double ld) -{ - register long exp; - register union double_long dl; - register union long_double_long ldl; - - ldl.ld = ld; - /*printf ("xfdf in: %s\n", dumpxf (ld));*/ - - dl.l.upper = SIGNX (ldl); - if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower) - { - dl.l.lower = 0; - return dl.d; - } - - exp = EXPX (ldl) - EXCESSX + EXCESSD; - /* ??? quick and dirty: keep `exp' sane */ - if (exp >= EXPDMASK) - exp = EXPDMASK - 1; - dl.l.upper |= exp << (32 - (EXPDBITS + 1)); - /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */ - dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1); - dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1)); - dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1); - - /*printf ("xfdf out: %g\n", dl.d);*/ - return dl.d; -} - /* convert a float to a long double */ long double __extendsfxf2 (float f) @@ -571,6 +541,8 @@ __negxf2 (long double x1) return - (double) x1; } +#else + long __cmpxf2 (long double x1, long double x2) { @@ -613,5 +585,38 @@ __gexf2 (long double x1, long double x2) return __cmpdf2 ((double) x1, (double) x2); } +/* convert long double to double */ +double +__truncxfdf2 (long double ld) +{ + register long exp; + register union double_long dl; + register union long_double_long ldl; + + ldl.ld = ld; + /*printf ("xfdf in: %s\n", dumpxf (ld));*/ + + dl.l.upper = SIGNX (ldl); + if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower) + { + dl.l.lower = 0; + return dl.d; + } + + exp = EXPX (ldl) - EXCESSX + EXCESSD; + /* ??? quick and dirty: keep `exp' sane */ + if (exp >= EXPDMASK) + exp = EXPDMASK - 1; + dl.l.upper |= exp << (32 - (EXPDBITS + 1)); + /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */ + dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1); + dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1)); + dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1); + + /*printf ("xfdf out: %g\n", dl.d);*/ + return dl.d; +} +#endif /* EXTFLOATCMP */ + #endif /* !__mcoldfire__ */ #endif /* EXTFLOAT */ diff --git a/libgcc/config/m68k/t-floatlib b/libgcc/config/m68k/t-floatlib index 42f6cf97ef48..2365433a59b3 100644 --- libgcc/config/m68k/t-floatlib +++ libgcc/config/m68k/t-floatlib @@ -6,51 +6,57 @@ # _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2 # -LIB2ADD = xfgnulib.c xfgnulib__unordsf2.c xfgnulib__unorddf2.c \ - xfgnulib__floatunsidf.c xfgnulib__floatsidf.c xfgnulib__floatunsisf.c \ - xfgnulib__floatsisf.c xfgnulib__extendsfdf2.c xfgnulib__truncdfsf2.c \ - xfgnulib__fixdfsi.c xfgnulib__fixsfsi.c - -xfgnulib__unordsf2.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __UNORDSF2' > xfgnulib__unordsf2.c - cat $< >> xfgnulib__unordsf2.c - -xfgnulib__unorddf2.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __UNORDDF2' > xfgnulib__unorddf2.c - cat $< >> xfgnulib__unorddf2.c - -xfgnulib__floatunsidf.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __FLOATUNSIDF' > xfgnulib__floatunsidf.c - cat $< >> xfgnulib__floatunsidf.c - -xfgnulib__floatsidf.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __FLOATSIDF' > xfgnulib__floatsidf.c - cat $< >> xfgnulib__floatsidf.c - -xfgnulib__floatunsisf.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __FLOATUNSISF' > xfgnulib__floatunsisf.c - cat $< >> xfgnulib__floatunsisf.c - -xfgnulib__floatsisf.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __FLOATSISF' > xfgnulib__floatsisf.c - cat $< >> xfgnulib__floatsisf.c - -xfgnulib__extendsfdf2.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __EXTENDSFDF2' > xfgnulib__extendsfdf2.c - cat $< >> xfgnulib__extendsfdf2.c - -xfgnulib__truncdfsf2.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __TRUNCDFSF2' > xfgnulib__truncdfsf2.c - cat $< >> xfgnulib__truncdfsf2.c - -xfgnulib__fixdfsi.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __FIXDFSI' > xfgnulib__fixdfsi.c - cat $< >> xfgnulib__fixdfsi.c - -xfgnulib__fixsfsi.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define __FIXSFSI' > xfgnulib__fixsfsi.c - cat $< >> xfgnulib__fixsfsi.c - -xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c - echo '#define EXTFLOAT' > xfgnulib.c - cat $< >> xfgnulib.c +LIB2ADD = xfpgnulib.c xfpgnulib__unordsf2.c xfpgnulib__unorddf2.c \ + xfpgnulib__floatunsidf.c xfpgnulib__floatsidf.c xfpgnulib__floatunsisf.c \ + xfpgnulib__floatsisf.c xfpgnulib__extendsfdf2.c xfpgnulib__truncdfsf2.c \ + xfpgnulib__fixdfsi.c xfpgnulib__fixsfsi.c xfpgnulib__cmpxf2.c + +xfpgnulib__unordsf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __UNORDSF2' > xfpgnulib__unordsf2.c + cat $< >> xfpgnulib__unordsf2.c + +xfpgnulib__unorddf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __UNORDDF2' > xfpgnulib__unorddf2.c + cat $< >> xfpgnulib__unorddf2.c + +xfpgnulib__floatunsidf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATUNSIDF' > xfpgnulib__floatunsidf.c + cat $< >> xfpgnulib__floatunsidf.c + +xfpgnulib__floatsidf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATSIDF' > xfpgnulib__floatsidf.c + cat $< >> xfpgnulib__floatsidf.c + +xfpgnulib__floatunsisf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATUNSISF' > xfpgnulib__floatunsisf.c + cat $< >> xfpgnulib__floatunsisf.c + +xfpgnulib__floatsisf.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FLOATSISF' > xfpgnulib__floatsisf.c + cat $< >> xfpgnulib__floatsisf.c + +xfpgnulib__extendsfdf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __EXTENDSFDF2' > xfpgnulib__extendsfdf2.c + cat $< >> xfpgnulib__extendsfdf2.c + +xfpgnulib__truncdfsf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __TRUNCDFSF2' > xfpgnulib__truncdfsf2.c + cat $< >> xfpgnulib__truncdfsf2.c + +xfpgnulib__fixdfsi.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FIXDFSI' > xfpgnulib__fixdfsi.c + cat $< >> xfpgnulib__fixdfsi.c + +xfpgnulib__fixsfsi.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define __FIXSFSI' > xfpgnulib__fixsfsi.c + cat $< >> xfpgnulib__fixsfsi.c + +xfpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define EXTFLOAT' > xfpgnulib.c + cat $< >> xfpgnulib.c + +xfpgnulib__cmpxf2.c: $(srcdir)/config/m68k/fpgnulib.c + echo '#define EXTFLOAT' > xfpgnulib__cmpxf2.c + echo '#define EXTFLOATCMP' >> xfpgnulib__cmpxf2.c + cat $< >> xfpgnulib__cmpxf2.c + \ No newline at end of file From 97a50aa76b592060171013c4a00ac472d8711580 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 18 Oct 2017 19:45:35 +0200 Subject: [PATCH 224/303] eliminating redundant loads (move.l reg,reg) is checking that the source value is still known --- gcc/bbb-opts.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index fe7cd79b5c7b..6e257b22266a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3755,11 +3755,16 @@ opt_elim_dead_assign (unsigned blocked_regno) rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; rtx cached_value2 = 0; if (cached_value && REG_P(cached_value) && REGNO(cached_value) < FIRST_PSEUDO_REGISTER) - cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)]; + { + cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)]; + if (!cached_value2) // no value for the reg -> reg is invalid too + cached_value = 0; + } if (cached_value && (rtx_equal_p (cached_value, SET_SRC(set)) || (cached_value2 && rtx_equal_p (cached_value2, SET_SRC(set))))) { +// fprintf(stderr, "cached_value: "); debug_rtx(cached_value); log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); SET_INSN_DELETED(insn); ++change_count; From b9e0de6883c5bcf3c58828453cc601b889a07516 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 18 Oct 2017 19:47:25 +0200 Subject: [PATCH 225/303] bump DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c4335f1aad48..c95c776f3dcf 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171011-233828 +20171018-194704 From 068a438a7b99afeed45bb95c08dd38ea94f0280a Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 11 Nov 2017 15:01:03 +0100 Subject: [PATCH 226/303] improved insn checking and auto inc --- gcc/bbb-opts.c | 458 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 275 insertions(+), 183 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 6e257b22266a..c6aaa4dcb476 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -53,6 +53,9 @@ */ #include "config.h" +#define INCLUDE_VECTOR +#define INCLUDE_SET +#define INCLUDE_MAP #include "system.h" #include "coretypes.h" #include "backend.h" @@ -67,11 +70,6 @@ #include "tree-pass.h" #include "conditions.h" #include "langhooks.h" -#include -#include -#include - -static int xx = 0; int be_very_verbose; bool be_verbose; @@ -274,6 +272,9 @@ class insn_info void absolute2base (unsigned regno, unsigned base, rtx with_symbol); + rtx + make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, bool apply); + inline bool is_compare () const { @@ -776,7 +777,7 @@ class insn_info void scan_rtx (rtx); - void + bool make_post_inc (int regno); void @@ -822,14 +823,16 @@ class insn_info a5_to_a7 (rtx a7); }; -void +bool insn_info::make_post_inc (int regno) { + rtx pattern = PATTERN(insn); + rtx_insn * new_insn = make_insn_raw(pattern); + // convert into POST_INC -// debug_rtx (insn); - rtx set0 = single_set (insn); + rtx set0 = single_set (new_insn); rtx set = set0; - SET_INSN_DELETED(insn); + if (is_compare ()) set = SET_SRC(set); rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); @@ -837,21 +840,60 @@ insn_info::make_post_inc (int regno) mem = XEXP(mem, 1); rtx reg = XEXP(mem, 0); + XEXP(mem, 0) = gen_rtx_POST_INC(SImode, reg); + if (insn_invalid_p (new_insn, 0)) + { + XEXP(mem, 0) = reg; + insn_invalid_p (insn, 0); + return 0; + } + + SET_INSN_DELETED(insn); (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode); - insn = emit_insn_after (set0, insn); -// debug_rtx (insn); + insn = emit_insn_after (PATTERN(new_insn), insn); + insn_invalid_p(insn, 0); + + return 1; +} + +static rtx +add_clobbers (rtx_insn * oldinsn) +{ + rtx pattern = PATTERN (oldinsn); + if (GET_CODE(pattern) != PARALLEL) + return pattern; + + int num_clobbers = 0; + for (int j = XVECLEN (pattern, 0) - 1; j >= 0; j--) + { + rtx x = XVECEXP(pattern, 0, j); + if (GET_CODE(x) == CLOBBER) + ++num_clobbers; + } + + if (!num_clobbers) + return pattern; + + rtx newpat = gen_rtx_PARALLEL(VOIDmode, rtvec_alloc (num_clobbers + 1)); + for (int j = XVECLEN (pattern, 0) - 1; j >= 0; j--) + { + rtx x = XVECEXP(pattern, 0, j); + if (GET_CODE(x) == CLOBBER) + XVECEXP(newpat, 0, num_clobbers--) = x; + } + + XVECEXP(newpat, 0, 0) = XVECEXP(pattern, 0, 0); + return newpat; } void insn_info::auto_inc_fixup (int regno, int size) { // debug_rtx (insn); - rtx set0 = single_set (insn); rtx set = set0; - SET_INSN_DELETED(insn); if (is_compare ()) set = SET_SRC(set); @@ -876,7 +918,7 @@ insn_info::auto_inc_fixup (int regno, int size) mem = XEXP(mem, 1); rtx plus = XEXP(mem, 0); - if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == size) + if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == (unsigned) size) { XEXP(mem, 0) = XEXP(plus, 0); (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) = 0; @@ -886,8 +928,11 @@ insn_info::auto_inc_fixup (int regno, int size) XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size); } - insn = emit_insn_after (set0, insn); -// debug_rtx (insn); + + rtx pattern = add_clobbers (insn); + + SET_INSN_DELETED(insn); + insn = emit_insn_after (pattern, insn); } track_var * @@ -1383,15 +1428,14 @@ insn_info::set_insn (rtx_insn * newinsn) fledder (single_set (insn)); } -void -insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) +rtx +insn_info::make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, bool apply) { rtx set = single_set (get_insn ()); rtx src = SET_SRC(set); rtx dst = SET_DEST(set); - bool vola = src->volatil; - rtx pattern; rtx reg = gen_raw_REG (SImode, regno); + bool vola = src->volatil; if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol) { @@ -1404,10 +1448,13 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) else dst = gen_rtx_MEM (mode, gen_rtx_PLUS(SImode, reg, gen_rtx_CONST_INT (SImode, offset))); - dst_mem_reg = reg; - dst_mem = true; - dst_mem_addr = offset; - dst_plus = offset != 0; + if (apply) + { + dst_mem_reg = reg; + dst_mem = true; + dst_mem_addr = offset; + dst_plus = offset != 0; + } } } @@ -1438,16 +1485,27 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) } } - src_mem_reg = reg; - src_mem = true; - src_mem_addr = offset; - src_plus = offset != 0; + if (apply) + { + src_mem_reg = reg; + src_mem = true; + src_mem_addr = offset; + src_plus = offset != 0; + } } } - pattern = gen_rtx_SET(dst, src); + rtx pattern = gen_rtx_SET(dst, src); src->volatil = vola; + return pattern; +} + +void +insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol) +{ + rtx pattern = make_absolute2base (regno, base, with_symbol, true); + SET_INSN_DELETED(insn); insn = emit_insn_after (pattern, insn); @@ -1506,7 +1564,7 @@ append_reg_usage (FILE * f, rtx_insn * insn) if (be_very_verbose > 1) fprintf (f, "\n\t\t\t\t\t|%d\t", ii.get_index ()); else - fprintf (f, "\n\t\t\t\t\t|\t", ii.get_index ()); + fprintf (f, "\n\t\t\t\t\t|\t"); } fprintf (f, "%c ", ii.in_proepi () == IN_PROLOGUE ? 'p' : ii.in_proepi () >= IN_EPILOGUE ? 'e' : ' '); @@ -1533,6 +1591,22 @@ append_reg_usage (FILE * f, rtx_insn * insn) if (ii.is_use (FIRST_PSEUDO_REGISTER)) fprintf (f, ii.is_def (FIRST_PSEUDO_REGISTER) ? "+cc " : " cc "); + else + fprintf (f, " "); + + // append fp usage info if present + if ((ii.get_use () | ii.get_def ()) & ~0xffff) + { + for (int j = 16; j < 24; ++j) + if (ii.is_use (j) || ii.is_def (j)) + { + fprintf (f, ii.is_hard (j) ? "!" : " "); + fprintf (f, ii.is_def (j) ? ii.is_use (j) ? "*" : "+" : ii.is_myuse (j) ? "." : " "); + fprintf (f, "f%d ", j - 16); + } + else + fprintf (f, " "); + } if (f == stderr) fprintf (f, "\n"); @@ -2024,7 +2098,6 @@ opt_reg_rename (void) if (found.find (startat) != found.end () || !infos[startat].is_use (rename_regno)) continue; - unsigned start = find_start (startat, rename_regno); // printf ("label %d <- jump %d : start %d\n", pos, startat, start); fflush (stdout); todo.insert (start); @@ -2042,7 +2115,7 @@ opt_reg_rename (void) // printf ("label start check %d use %d\n", pos, bb.is_use (rename_regno) || bb.is_def(rename_regno)); fflush (stdout); - if (bb.is_use (rename_regno) || bb.is_def(rename_regno)) + if (bb.is_use (rename_regno) || bb.is_def (rename_regno)) { unsigned start = find_start (pos - 1, rename_regno); todo.insert (start); @@ -2136,15 +2209,14 @@ opt_reg_rename (void) for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) { - rtx_insn * insn = infos[*i].get_insn (); + insn_info & rr = infos[*i]; + rtx_insn * insn = rr.get_insn (); /* temp rename. */ temp_reg_rename (locs, PATTERN (insn), oldregno, newregno); if (!locs.empty ()) { - int num_clobbers_to_add = 0; - int insn_code_number = recog (PATTERN (insn), insn, &num_clobbers_to_add); - if (insn_code_number < 0 || !check_asm_operands (PATTERN (insn))) + if (insn_invalid_p (insn, 1)) ok = false; /* undo temp change but keep loc and new register. */ @@ -2160,6 +2232,12 @@ opt_reg_rename (void) } if (!ok) + { + cancel_changes (0); + continue; + } + + if (!apply_change_group ()) continue; log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], @@ -2527,18 +2605,15 @@ opt_strcpy () NOTICE_UPDATE_CC(PATTERN (reg2x), reg2x); if (cc_status.flags == 0 && rtx_equal_p (dst, cc_status.value2)) { - int num_clobbers_to_add = 0; - int insn_code_number; - rtx pattern = gen_rtx_SET(SET_DEST(single_set (reg2x)), SET_SRC(single_set (x2reg))); rtx_insn * newinsn = make_insn_raw (pattern); - insn_code_number = recog (PATTERN (newinsn), newinsn, &num_clobbers_to_add); - if (insn_code_number >= 0 && check_asm_operands (PATTERN (newinsn))) + + if (!insn_invalid_p (newinsn, 0)) { log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", reg_names[REGNO(dst)]); - emit_insn_after (pattern, reg2x); + emit_insn_after (newinsn, reg2x); SET_INSN_DELETED(x2reg); SET_INSN_DELETED(reg2x); @@ -2646,21 +2721,21 @@ opt_commute_add_move (void) rtx newmem = replace_equiv_address_nv (dst, pinc); rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src)); - if (recog (PATTERN (newinsn), newinsn, 0) < 0 || !check_asm_operands (PATTERN (newinsn))) - continue; - if (validate_change (next, &SET_DEST(set2), newmem, 0)) + if (!insn_invalid_p (newinsn, 1) && validate_change (next, &SET_DEST(set2), newmem, 1) && apply_change_group ()) { log ("(a) commute_add_move found\n"); SET_INSN_DELETED(insn); - insn = emit_insn_before (PATTERN (newinsn), next); + insn = emit_insn_before (newinsn, next); add_reg_note (next, REG_INC, reg1dst); ++change_count; } + else + cancel_changes (0); } return change_count; } @@ -2722,8 +2797,8 @@ opt_const_cmp_to_sub (void) lastsubval = pp.get_src_intval (); // but still check for usage after this jump - j2l_iterator l = jump2label.find(index + 2); - if (l == jump2label.end()) + j2l_iterator l = jump2label.find (index + 2); + if (l == jump2label.end ()) continue; insn_info & label = infos[l->second + 1]; @@ -2785,9 +2860,7 @@ opt_const_cmp_to_sub (void) rtx_insn * subinsn = make_insn_raw (gen_rtx_SET(copyreg, sub)); - int num_clobbers_to_add = 0; - int insn_code_number = recog (PATTERN (subinsn), subinsn, &num_clobbers_to_add); - if (insn_code_number < 0 || !check_asm_operands (PATTERN (subinsn))) + if (insn_invalid_p (subinsn, 0)) continue; /* delete move #x,dy. */ @@ -3726,7 +3799,7 @@ track_regs () * delete those insns. */ static unsigned -opt_elim_dead_assign (unsigned blocked_regno) +opt_elim_dead_assign (int blocked_regno) { track_regs (); @@ -3885,6 +3958,7 @@ opt_absolute (void) if (freemask && found.size () > 2) { + unsigned regno = bit2regno (freemask); /* check again. */ for (std::vector::iterator k = found.begin (); k != found.end ();) { @@ -3897,6 +3971,8 @@ opt_absolute (void) k = found.erase (k); else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc) k = found.erase (k); + else if (insn_invalid_p (make_insn_raw (kk.make_absolute2base (regno, base, with_symbol, false)), 0)) + k = found.erase (k); else ++k; } @@ -3916,6 +3992,7 @@ opt_absolute (void) { insn_info & kk = infos[*k]; kk.absolute2base (regno, base, with_symbol); + insn_invalid_p (kk.get_insn (), 0); } // load base into reg @@ -3958,174 +4035,194 @@ opt_absolute (void) return change_count; } -/* - * Convert a series of reg with offset ( (ax), 4(ax), 8(ax), ...) into autoincx ( (ax+), (ax+), (ax+), ...) - * - * 1. search a mem(reg) without offset and either src or dst is using that reg - * 2. follow paths until reg is dead - * 3. if there is another mem(reg) with offset check that - * a) offset fits last mode size - * b) all remaining insn using that reg can be updated by - * i) decrement the offset - * ii) decrement the add value - */ -static unsigned -opt_autoinc () +static int +try_auto_inc (unsigned index, insn_info & ii, rtx reg) { - unsigned change_count = 0; + int regno = REGNO(reg); + unsigned size = GET_MODE_SIZE(ii.get_mode ()); + if (size > 4) + return 0; - update_label2jump (); +// log ("starting auto_inc search for %s at %d\n", reg_names[regno], index); - for (unsigned index = 0; index < infos.size (); ++index) - { - insn_info & ii = infos[index]; + // track all fixups to modify + std::set fixups; - if (ii.in_proepi ()) - continue; + // all paths to check + std::vector todo; + todo.push_back (index + 1); - rtx reg = 0; - if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc () - && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) - reg = ii.get_src_mem_reg (); - if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () - && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) - reg = ii.get_dst_mem_reg (); - if (!reg) - continue; + bool match_size = false; + bool ok = true; + std::set visited; + while (ok && todo.size () > 0) + { + unsigned pos = todo[todo.size () - 1]; + todo.pop_back (); - int regno = REGNO(reg); - int size = GET_MODE_SIZE(ii.get_mode ()); - if (size > 4) - continue; + if (pos == index) + { + ok = false; + break; + } -// log ("starting auto_inc search for %s at %d\n", reg_names[regno], index); + if (visited.find (pos) != visited.end ()) + continue; + visited.insert (pos); - // track all fixups to modify - std::set fixups; + for (; pos < infos.size (); ++pos) + { + insn_info & jj = infos[pos]; - // all paths to check - std::vector todo; - todo.push_back (index + 1); + // check all jumps labels for register usage + if (jj.is_label ()) + { + for (l2j_iterator j = label2jump.find (jj.get_insn ()->u2.insn_uid), k = j; + j != label2jump.end () && j->first == k->first; ++j) + { + insn_info * ll = insn2info.find (j->second)->second; + if (ll->is_use (regno)) + { + ok = false; + break; + } + } + if (ok) + continue; + break; + } - bool match_size = false; - bool ok = true; - std::set visited; - while (ok && todo.size () > 0) - { - unsigned pos = todo[todo.size () - 1]; - todo.pop_back (); + // break if no longer used + if (!jj.is_use (regno)) + break; - if (pos == index) + if (jj.in_proepi ()) { ok = false; break; } - if (visited.find (pos) != visited.end ()) + // add all labels + if (jj.is_jump ()) + { + for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first; ++j) + todo.push_back (j->second); + continue; + } + + // not used directly + if (!jj.is_myuse (regno)) continue; - visited.insert (pos); - for (; pos < infos.size (); ++pos) + // can't fixup such kind of insn (yet) + if (single_set (jj.get_insn ()) == 0) { - insn_info & jj = infos[pos]; + ok = false; + break; + } - // check all jumps labels for register usage - if (jj.is_label ()) + // if reg is src reg, op must be add and addend must be large enough + if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno) + { + if (jj.get_src_intval () < (int) size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size)) { - for (l2j_iterator j = label2jump.find (jj.get_insn ()->u2.insn_uid), k = j; - j != label2jump.end () && j->first == k->first; ++j) - { - insn_info * ll = insn2info.find (j->second)->second; - if (ll->is_use (regno)) - { - ok = false; - break; - } - } - if (ok) - continue; + ok = false; break; } - // break if no longer used - if (!jj.is_use (regno)) - break; + if (jj.get_dst_addr () == size) + match_size = true; - if (jj.in_proepi ()) + fixups.insert (pos); + } + else if (jj.get_dst_mem_regno () == regno) + { + if (jj.get_dst_addr () < size) { ok = false; break; } - // add all labels - if (jj.is_jump ()) - { - for (j2l_iterator j = jump2label.find (pos), k = j; j != jump2label.end () && j->first == k->first; - ++j) - todo.push_back (j->second); - continue; - } + if (jj.get_dst_addr () == size) + match_size = true; - // not used directly - if (!jj.is_myuse (regno)) - continue; + fixups.insert (pos); + } + else + { + ok = false; + break; + } - // if reg is src reg, op must be add and addend must be large enough - if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno) - { - if (jj.get_src_intval () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size)) - { - ok = false; - break; - } + // done if this is an add + if (ii.is_def (regno)) + break; + } + } - if (jj.get_dst_addr () == size) - match_size = true; + if (!ok || !match_size || !fixups.size ()) + return 0;; - fixups.insert (pos); - } - else if (jj.get_dst_mem_regno () == regno) - { - if (jj.get_dst_addr () < size) - { - ok = false; - break; - } + if (!ii.make_post_inc (regno)) + return 0; - if (jj.get_dst_addr () == size) - match_size = true; + log ("(i) auto_inc for %s at %d\n", reg_names[regno], index); - fixups.insert (pos); - } - else - { - ok = false; - break; - } + // fix all offsets / adds + for (std::set::iterator k = fixups.begin (); k != fixups.end (); ++k) + { +// log ("(i) fixup at %d\n", *k); + insn_info & kk = infos[*k]; + kk.auto_inc_fixup (regno, size); + } + return 1; +} - // done if this is an add - if (ii.is_def (regno)) - break; - } - } +/* + * Convert a series of reg with offset ( (ax), 4(ax), 8(ax), ...) into autoincx ( (ax+), (ax+), (ax+), ...) + * + * 1. search a mem(reg) without offset and either src or dst is using that reg + * 2. follow paths until reg is dead + * 3. if there is another mem(reg) with offset check that + * a) offset fits last mode size + * b) all remaining insn using that reg can be updated by + * i) decrement the offset + * ii) decrement the add value + */ +static unsigned +opt_autoinc () +{ + unsigned change_count = 0; + + update_label2jump (); + + for (unsigned index = 0; index < infos.size (); ++index) + { + insn_info & ii = infos[index]; + + if (ii.in_proepi ()) + continue; - if (!ok || !match_size || !fixups.size ()) + if (!INSN_P(ii.get_insn ())) continue; - log ("(i) auto_inc for %s at %d\n", reg_names[regno], index); +// // more than one reg used +// if (ii.get_myuse () & (ii.get_myuse () - 1)) +// continue; - ii.make_post_inc (regno); +// // don't if fp regs are touched +// if ((ii.get_myuse () & 0xff0000)) +// continue; - // fix all offsets / adds - for (std::set::iterator k = fixups.begin (); k != fixups.end (); ++k) - { -// log ("(i) fixup at %d\n", *k); - insn_info & kk = infos[*k]; - kk.auto_inc_fixup (regno, size); - } + rtx reg = 0; + if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc () + && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ()); + + if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () + && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + change_count += try_auto_inc (index, ii, ii.get_dst_mem_reg ()); - ++change_count; - --index; // rerun insn to check src and dst } return change_count; @@ -4207,11 +4304,6 @@ namespace bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); -// ++xx; -// printf ("x: %d\n", xx); -// if (xx <= 48 || xx > 54) -// do_autoinc = false; - if (be_very_verbose) log ("ENTER\n"); From 5c2dd1b12baffbf3e34da07e5fec09452f251d9e Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 12 Nov 2017 18:43:05 +0100 Subject: [PATCH 227/303] autoinc improved, new register tracking is incorrect --- gcc/bbb-opts.c | 308 +++++++++++++++++++++++++++------------------------------ 1 file changed, 145 insertions(+), 163 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index c6aaa4dcb476..55cfae075f36 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -118,69 +118,72 @@ enum proepis class track_var { + unsigned * indexes; rtx * values; unsigned * versions; public: track_var (track_var const * o = 0) : - values ((rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions ( + indexes ((unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))), values ( + (rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions ( (unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))) { if (o) assign (o); } - rtx * - get_values () const + void + set (unsigned regno, unsigned index, rtx rtx, unsigned ver) { - return values; + if (regno >= FIRST_PSEUDO_REGISTER) + return; + + indexes[regno] = index; + values[regno] = rtx; + versions[regno] = ver; } - void - set_version (unsigned regno, unsigned ver) - { - if (regno < FIRST_PSEUDO_REGISTER) - versions[regno] = ver; + unsigned get_index(unsigned regno) const { + return indexes[regno]; + } + + rtx get_value(unsigned regno) const { + return values[regno]; + } + + unsigned get_version(unsigned regno) const { + return versions[regno]; } void assign (track_var const * o) const { + memcpy (indexes, o->indexes, FIRST_PSEUDO_REGISTER * sizeof(unsigned)); memcpy (values, o->values, FIRST_PSEUDO_REGISTER * sizeof(rtx)); memcpy (versions, o->versions, FIRST_PSEUDO_REGISTER * sizeof(unsigned)); } /* only keep common values in both sides. */ void - merge (track_var * o) + merge (track_var * o, unsigned at) { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i])) - { - int code = GET_CODE(values[i]); - if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i]) - values[i] = o->values[i] = 0; - } - else + indexes[i] = at; + if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i])) values[i] = o->values[i] = 0; } } /* true if a merge would not change anything. */ bool - contains (track_var const * o) const + no_merge_needed (track_var const * o) const { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - if (values[i] && o->values[i] && rtx_equal_p (values[i], o->values[i])) - { - int code = GET_CODE(values[i]); - if (code != CONST_INT && code != CONST_FIXED && code != CONST_DOUBLE && versions[i] != o->versions[i]) - return false; - } - else if (values[i]) - return false; + if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i])) + if (values[i]) + return false; } return true; } @@ -365,7 +368,7 @@ class insn_info } inline unsigned - get_dst_addr () const + get_dst_mem_addr () const { return dst_mem_addr; } @@ -826,8 +829,8 @@ class insn_info bool insn_info::make_post_inc (int regno) { - rtx pattern = PATTERN(insn); - rtx_insn * new_insn = make_insn_raw(pattern); + rtx pattern = PATTERN (insn); + rtx_insn * new_insn = make_insn_raw (pattern); // convert into POST_INC rtx set0 = single_set (new_insn); @@ -852,8 +855,8 @@ insn_info::make_post_inc (int regno) SET_INSN_DELETED(insn); (get_dst_mem_regno () == regno ? dst_autoinc : src_autoinc) = GET_MODE_SIZE(mode); - insn = emit_insn_after (PATTERN(new_insn), insn); - insn_invalid_p(insn, 0); + insn = emit_insn_after (PATTERN (new_insn), insn); + insn_invalid_p (insn, 0); return 1; } @@ -1010,11 +1013,15 @@ insn_info::scan_rtx (rtx x) unsigned u = use; unsigned mu = myuse; use = myuse = 0; - scan_rtx (SET_DEST(x)); - if (REG_P(SET_DEST(x))) + rtx dst = SET_DEST(x); + scan_rtx (dst); + if (REG_P(dst) || ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG) && REG_P(XEXP(dst, 0)))) { def |= use; - use = u; + if ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG)) + use |= u; + else + use = u; myuse = mu; } scan_rtx (SET_SRC(x)); @@ -1439,7 +1446,7 @@ insn_info::make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, b if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol) { - unsigned addr = get_dst_addr (); + unsigned addr = get_dst_mem_addr (); unsigned offset = addr - base; if (offset <= 0x7ffe) { @@ -3591,7 +3598,55 @@ opt_shrink_stack_frame (void) return changed; } -/* Update the insn_infos to 'know' the value for each register. */ +/* Update the insn_infos to 'know' the value for each register. + * + * atm only assignments to registers are optimized. + * + * We track register aliases: + * + * ;10 + * move.l 4(a0),d0 + * + * ;15 + * move.l d0,d1 + * + * + * ;18 + * move.l d1,d2 + * + * - results into d0 is an alias for d1 (and vice versa). + * - to identify if a register is still changed, we also track the line where it was assigned. + * - in addition to register aliases memory reads are tracked too for normal memory access (e.g. no auto inc) + * but not if the memory read is marked as volatile + * + * E.g. + * + * d0[10]: 4(a0)[10] + * d1[15]: d0[10] + * d2[18]: d1[15] + * + * with that information we know that d2[18] also contains 4(a0)[10] + * + * info to track per register: + * line index where the value was assigned + * rtx which was assigned - or null if not a usable rtx + * reg line index - if rtx is a register + * + * for each assignment which is not to a register the rtx are scanned and set to null on match + * + * on jumps the current state is duplicated and merged at the given label + * + * on merge only identical info is kept, rest is discarded + * + * for each insn first the track info for all defined regs is discarded before the new one is set. + * + * + * after the track info is complete, each insn is evaluated agains the track info. + * + * now redundant loads are found and eliminated + * also unused assignments are found an eliminated + * + */ static unsigned track_regs () { @@ -3615,47 +3670,21 @@ track_regs () track_var * const track = todo.begin ()->second; todo.erase (todo.begin ()); - rtx * values = track->get_values (); - // track register aliases: know which register is used in what slot - // if a register changes, invalidate each slot - std::multimap reg2slot; - for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot) - if (values[slot]) - { - insn_info vv; - vv.scan_rtx (values[slot]); - for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1) - if (m & 1) - reg2slot.insert (std::make_pair (regno, slot)); - } - - unsigned version = startpos; for (unsigned index = startpos; index < infos.size (); ++index) { insn_info & ii = infos[index]; // already visited? - if (index != startpos && ii.is_visited () && ii.get_track_var ()->contains (track)) + if (index != startpos && ii.is_visited () && ii.get_track_var ()->no_merge_needed(track)) break; // only keep common values at labels if (ii.is_label ()) { - version = index; if (ii.is_visited ()) { - ii.get_track_var ()->merge (track); - reg2slot.clear (); - for (unsigned slot = 0; slot < FIRST_PSEUDO_REGISTER; ++slot) - if (values[slot]) - { - insn_info vv; - vv.scan_rtx (values[slot]); - for (unsigned regno = 0, m = vv.get_myuse (); m; ++regno, m >>= 1) - if (m & 1) - reg2slot.insert (std::make_pair (regno, slot)); - } + ii.get_track_var ()->merge (track, index); } else { @@ -3675,18 +3704,11 @@ track_regs () unsigned def = ii.get_def (); if (def) { - for (int regno = 0; regno < 16; ++regno) - if ((1 << regno) & def) - { - values[regno] = 0; - // invalidate all referring registers - for (std::multimap::iterator j = reg2slot.find (regno), k = j; - j != reg2slot.end () && j->first == k->first;) - { - values[j->second] = 0; - j = reg2slot.erase (j); - } - } + for (int regno = 0; regno < 24; ++regno) + { + if ((1 << regno) & def) + track->set(regno, index, 0, index); + } } if (ii.is_call ()) @@ -3704,90 +3726,53 @@ track_regs () todo.insert (std::make_pair (i->second, new track_var (track))); if (set && GET_CODE(SET_SRC(set)) == IF_THEN_ELSE) - { - version = index; continue; - } // unconditional jump break; } - if (!set) + if (!set || !ii.get_def ()) continue; - rtx src, dest; - if (ii.get_src_autoinc ()) - { - int regno = ii.get_src_mem_regno (); - values[regno] = 0; - for (std::multimap::iterator j = reg2slot.find (regno), k = j; - j != reg2slot.end () && j->first == k->first;) - { - values[j->second] = 0; - j = reg2slot.erase (j); - } - } - - if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ())) - src = 0; - else - { - src = SET_SRC(set); - if (ii.is_src_mem () && src->volatil) - src = 0; - } - - if (ii.get_dst_autoinc ()) + // invalidate all which are using the value from dest since that value changed + rtx dst = SET_DEST(set); + if (MEM_P(dst)) { - int regno = ii.get_dst_mem_regno (); - values[regno] = 0; - for (std::multimap::iterator j = reg2slot.find (regno), k = j; - j != reg2slot.end () && j->first == k->first;) + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - values[j->second] = 0; - j = reg2slot.erase (j); + if (rtx_equal_p(dst, track->get_value(i))) + track->set(i, index, 0, index); } } - if (src == 0 || ii.get_src_op () || ii.get_dst_autoinc ()) - dest = 0; - else - dest = SET_DEST(set); - - // track register values for now int dregno = ii.get_dst_regno (); - int sregno = ii.get_src_regno (); + if (dregno < 0) + continue; - // track reg2slot - if (dregno >= 0) - { - for (unsigned regno = 0, m = ii.get_myuse (); m; ++regno, m >>= 1) - if (m & 1) - reg2slot.insert (std::make_pair (regno, dregno)); + // operation, autoinf or more than one register used: can't cache + if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ())) + continue; - if (sregno >= 0) - { - reg2slot.insert (std::make_pair (dregno, sregno)); - reg2slot.insert (std::make_pair (sregno, dregno)); - } - } + rtx src = SET_SRC(set); + if (ii.is_src_mem () && src->volatil) + continue; - if (sregno >= 0) + // add the entry - determine the version - use 0 for const values + unsigned version; + if (GET_CODE(src) != CONST_INT && GET_CODE(src) != CONST_FIXED && GET_CODE(src) != CONST_DOUBLE) { - values[sregno] = dest; - track->set_version (sregno, version); - for (unsigned i = sregno + 1; i < END_REGNO (ii.get_src_reg ()); ++i) - values[i] = 0; + if (ii.get_src_regno() >= 0) + version = track->get_index(ii.get_src_regno()); + else if (ii.get_src_mem_regno() >= 0) + version = track->get_index(ii.get_src_mem_regno()); + else + version = index; } + else + version = 0; - if (dregno >= 0) - { - values[dregno] = src; - track->set_version (dregno, version); - for (unsigned i = dregno + 1; i < END_REGNO (ii.get_dst_reg ()); ++i) - values[i] = 0; - } + track->set(dregno, index, src, version); } delete track; } @@ -3822,26 +3807,23 @@ opt_elim_dead_assign (int blocked_regno) ++change_count; continue; } + + // check for redundant load if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno && !ii.is_use (ii.get_dst_regno ())) { - rtx cached_value = ii.get_track_var ()->get_values ()[ii.get_dst_regno ()]; - rtx cached_value2 = 0; - if (cached_value && REG_P(cached_value) && REGNO(cached_value) < FIRST_PSEUDO_REGISTER) - { - cached_value2 = ii.get_track_var ()->get_values ()[REGNO(cached_value)]; - if (!cached_value2) // no value for the reg -> reg is invalid too - cached_value = 0; - } - if (cached_value - && (rtx_equal_p (cached_value, SET_SRC(set)) - || (cached_value2 && rtx_equal_p (cached_value2, SET_SRC(set))))) + track_var * track = ii.get_track_var(); + rtx src = SET_SRC(set); + if (rtx_equal_p(track->get_value(ii.get_dst_regno()), src)) { -// fprintf(stderr, "cached_value: "); debug_rtx(cached_value); - log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); - SET_INSN_DELETED(insn); - ++change_count; - continue; + if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(REGNO(src))) + || !REG_P(src)) + { + log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; + } } } } @@ -3883,7 +3865,7 @@ opt_absolute (void) std::vector found; found.push_back (i); - int base = ii.get_dst_addr (); + int base = ii.get_dst_mem_addr (); int max = base; unsigned j = i + 1; for (; j < infos.size (); ++j) @@ -3916,7 +3898,7 @@ opt_absolute (void) if (j_dst) { - int addr = jj.get_dst_addr (); + int addr = jj.get_dst_mem_addr (); if (addr < base) { if (max - addr <= 0x7ffe) @@ -3967,7 +3949,7 @@ opt_absolute (void) && kk.get_dst_symbol () == with_symbol; bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg () && kk.get_src_symbol () == with_symbol; - if (k_dst && kk.get_dst_addr () - base > 0x7ffc) + if (k_dst && kk.get_dst_mem_addr () - base > 0x7ffc) k = found.erase (k); else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc) k = found.erase (k); @@ -4124,26 +4106,26 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) // if reg is src reg, op must be add and addend must be large enough if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno) { - if (jj.get_src_intval () < (int) size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size)) + if (jj.get_src_mem_addr () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_mem_addr () < size)) { ok = false; break; } - if (jj.get_dst_addr () == size) + if (jj.get_src_mem_addr () == size) match_size = true; fixups.insert (pos); } else if (jj.get_dst_mem_regno () == regno) { - if (jj.get_dst_addr () < size) + if (jj.get_dst_mem_addr () < size) { ok = false; break; } - if (jj.get_dst_addr () == size) + if (jj.get_dst_mem_addr () == size) match_size = true; fixups.insert (pos); From aa0ae94cf14aa246fb5f1907a086615e39278b3a Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 13 Nov 2017 22:20:19 +0100 Subject: [PATCH 228/303] improved opt_autoinc() plus some bug fixes --- gcc/bbb-opts.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index c6aaa4dcb476..20126991e5d2 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -365,7 +365,7 @@ class insn_info } inline unsigned - get_dst_addr () const + get_dst_mem_addr () const { return dst_mem_addr; } @@ -1010,10 +1010,14 @@ insn_info::scan_rtx (rtx x) unsigned u = use; unsigned mu = myuse; use = myuse = 0; - scan_rtx (SET_DEST(x)); - if (REG_P(SET_DEST(x))) + rtx dst = SET_DEST(x); + scan_rtx (dst); + if (REG_P(dst) || ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG) && REG_P(XEXP(dst, 0)))) { def |= use; + if ((GET_CODE(dst) == STRICT_LOW_PART || GET_CODE(dst) == SUBREG)) + use |= u; + else use = u; myuse = mu; } @@ -1439,7 +1443,7 @@ insn_info::make_absolute2base (unsigned regno, unsigned base, rtx with_symbol, b if (is_dst_mem () && (has_dst_addr () || get_dst_symbol ()) && !has_dst_memreg () && get_dst_symbol () == with_symbol) { - unsigned addr = get_dst_addr (); + unsigned addr = get_dst_mem_addr (); unsigned offset = addr - base; if (offset <= 0x7ffe) { @@ -3883,7 +3887,7 @@ opt_absolute (void) std::vector found; found.push_back (i); - int base = ii.get_dst_addr (); + int base = ii.get_dst_mem_addr (); int max = base; unsigned j = i + 1; for (; j < infos.size (); ++j) @@ -3916,7 +3920,7 @@ opt_absolute (void) if (j_dst) { - int addr = jj.get_dst_addr (); + int addr = jj.get_dst_mem_addr (); if (addr < base) { if (max - addr <= 0x7ffe) @@ -3967,7 +3971,7 @@ opt_absolute (void) && kk.get_dst_symbol () == with_symbol; bool k_src = kk.is_src_mem () && (kk.has_src_addr () || kk.get_src_symbol ()) && !kk.has_src_memreg () && kk.get_src_symbol () == with_symbol; - if (k_dst && kk.get_dst_addr () - base > 0x7ffc) + if (k_dst && kk.get_dst_mem_addr () - base > 0x7ffc) k = found.erase (k); else if (k_src && kk.get_src_mem_addr () - base > 0x7ffc) k = found.erase (k); @@ -4124,26 +4128,26 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) // if reg is src reg, op must be add and addend must be large enough if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno) { - if (jj.get_src_intval () < (int) size || (jj.get_dst_mem_regno () == regno && jj.get_dst_addr () < size)) + if (jj.get_src_mem_addr () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_mem_addr () < size)) { ok = false; break; } - if (jj.get_dst_addr () == size) + if (jj.get_src_mem_addr () == size) match_size = true; fixups.insert (pos); } else if (jj.get_dst_mem_regno () == regno) { - if (jj.get_dst_addr () < size) + if (jj.get_dst_mem_addr () < size) { ok = false; break; } - if (jj.get_dst_addr () == size) + if (jj.get_dst_mem_addr () == size) match_size = true; fixups.insert (pos); @@ -4216,7 +4220,7 @@ opt_autoinc () rtx reg = 0; if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc () - && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_mem_regno () != ii.get_dst_regno ()) change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ()); if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () @@ -4293,16 +4297,16 @@ namespace if (be_very_verbose) be_verbose = true; - bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); - bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+'); + bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+'); - bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+'); bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+'); - bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); - bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); + bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+'); + bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+'); + bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); + bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); if (be_very_verbose) log ("ENTER\n"); From 7a4225792c22aaab94d962e6890fb0deaddfd015 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 10:36:18 +0100 Subject: [PATCH 229/303] fix possible stack corruption if sp is used in assignments --- gcc/bbb-opts.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 20126991e5d2..d9b89c6e29ac 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2993,12 +2993,17 @@ opt_merge_add (void) static unsigned track_sp () { -// reset visited flags +// reset visited flags - also check if sp is used as REG src. for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; ii.clear_visited (); ii.set_sp_offset (0); + + // if sp is used as source, we cannot shrink the stack yet + // too complicated + if (ii.get_src_regno() == STACK_POINTER_REGNUM) + return -1; } // add entry point From 0ef223ac20734c9b1998f62b6bef5f04d9cbf789 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 10:37:11 +0100 Subject: [PATCH 230/303] update target-help to be complete and better readable --- gcc/config/m68k/amigaos.opt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 9c08ba43196e..770cff6a4bd5 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -45,4 +45,19 @@ Specify startup binary fbbb= Target RejectNegative Report Var(string_bbb_opts) Joined --fbbb=\t\tEnable Bebbo's optimizations. Default: -fbbb=+\n valid letters:\n\t\t+\t\tenable all\n\t\t-\t\tdisable all\n\t\ta\t\tadd move optimization\n\t\tc\t\tcompare to sub\n\t\te\t\teliminate dead assignments\n\t\tf\t\tshrink stack frame\n\t\tm\t\tmerge add statements\n\t\tp\t\tpropagate move pairs from loops\n\t\tr\t\tadditional reg rename pass\n\t\tv\t\tbe verbose\n\t\tx or X\t\tdump insns +-fbbb=Enable Bebbo's optimizations. \ ++ enable all optimizations \ +a commute add move instructions \ +b use register for base addresses \ +c convert load const and compare into a sub \ +e eliminate dead assignments + redundant loads \ +f shrink stack frame \ +i use post increment on addresses \ +m merge add and move statements \ +p propagate move assignment pairs out of loops \ +r register renaming to maybe save registers \ +s a strcpy optimization \ +v be verbose \ +V be very verbose \ +x dump insns \ +Default: -fbbb=+ From 09c4f1cf165378985667aa9a82c1fa0403e60dd2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 10:49:16 +0100 Subject: [PATCH 231/303] merge from devel1 --- gcc/bbb-opts.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 55cfae075f36..47902cea4658 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2996,12 +2996,17 @@ opt_merge_add (void) static unsigned track_sp () { -// reset visited flags +// reset visited flags - also check if sp is used as REG src. for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; ii.clear_visited (); ii.set_sp_offset (0); + + // if sp is used as source, we cannot shrink the stack yet + // too complicated + if (ii.get_src_regno() == STACK_POINTER_REGNUM) + return -1; } // add entry point @@ -4198,7 +4203,7 @@ opt_autoinc () rtx reg = 0; if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc () - && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_mem_regno () != ii.get_dst_regno ()) change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ()); if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () @@ -4275,16 +4280,16 @@ namespace if (be_very_verbose) be_verbose = true; - bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); bool do_commute_add_move = strchr (string_bbb_opts, 'a') || strchr (string_bbb_opts, '+'); - bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+'); + bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+'); - bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+'); bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+'); - bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+'); - bool do_absolute = strchr (string_bbb_opts, 'b') || strchr (string_bbb_opts, '+'); bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+'); + bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+'); + bool do_propagate_moves = strchr (string_bbb_opts, 'p') || strchr (string_bbb_opts, '+'); + bool do_bb_reg_rename = strchr (string_bbb_opts, 'r') || strchr (string_bbb_opts, '+'); + bool do_opt_strcpy = strchr (string_bbb_opts, 's') || strchr (string_bbb_opts, '+'); if (be_very_verbose) log ("ENTER\n"); From 3d8120f2ca2cedeba1b42ece6e7c75f216324614 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 11:11:17 +0100 Subject: [PATCH 232/303] beautify target-help --- gcc/config/m68k/amigaos.opt | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 770cff6a4bd5..d87f884f06b3 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -45,19 +45,19 @@ Specify startup binary fbbb= Target RejectNegative Report Var(string_bbb_opts) Joined --fbbb=Enable Bebbo's optimizations. \ -+ enable all optimizations \ -a commute add move instructions \ -b use register for base addresses \ -c convert load const and compare into a sub \ -e eliminate dead assignments + redundant loads \ -f shrink stack frame \ -i use post increment on addresses \ -m merge add and move statements \ -p propagate move assignment pairs out of loops \ -r register renaming to maybe save registers \ -s a strcpy optimization \ -v be verbose \ -V be very verbose \ -x dump insns \ +-fbbb=Enable Bebbo's optimizations. ++ enable all optimizations +a commute add move instructions +b use register for base addresses +c convert load const and compare into a sub +e eliminate dead assignments + redundant loads +f shrink stack frame +i use post increment on addresses +m merge add and move statements +p propagate move assignment pairs out of loops +r register renaming to maybe save registers +s a strcpy optimization +v be verbose +V be very verbose +x dump insns Default: -fbbb=+ From 3227e2247242531bd11713c4d6d12cec096196bc Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 17:21:21 +0100 Subject: [PATCH 233/303] reworked register tracking seems to work --- gcc/bbb-opts.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 47902cea4658..f971c402cf84 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -3706,14 +3706,19 @@ track_regs () if (ii.is_compare ()) continue; + int dregno = ii.get_dst_regno (); unsigned def = ii.get_def (); if (def) { - for (int regno = 0; regno < 24; ++regno) + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) { - if ((1 << regno) & def) + // register changed or used somehow + if ( ((1 << regno) & def) || (infos[track->get_index(regno)].get_myuse() & def)) track->set(regno, index, 0, index); } + // clear on self update + if (def & ii.get_myuse()) + track->set(dregno, index, 0, index); } if (ii.is_call ()) @@ -3740,18 +3745,6 @@ track_regs () if (!set || !ii.get_def ()) continue; - // invalidate all which are using the value from dest since that value changed - rtx dst = SET_DEST(set); - if (MEM_P(dst)) - { - for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) - { - if (rtx_equal_p(dst, track->get_value(i))) - track->set(i, index, 0, index); - } - } - - int dregno = ii.get_dst_regno (); if (dregno < 0) continue; From a8cd5ab8084d61d5d7ca31a840a737d4cf689022 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 17:43:56 +0100 Subject: [PATCH 234/303] fix opt_strcpy() --- gcc/bbb-opts.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f971c402cf84..ca6e2acadf4d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2620,12 +2620,13 @@ opt_strcpy () log ("(s) opt_strcpy condition met, removing compare and joining insns - omit reg %s\n", reg_names[REGNO(dst)]); - emit_insn_after (newinsn, reg2x); - SET_INSN_DELETED(x2reg); SET_INSN_DELETED(reg2x); SET_INSN_DELETED(insn); + insn = emit_insn_after (pattern, reg2x); + insn_invalid_p (insn, 0); + ++change_count; } } From 0521364bbbcab54adfecf35c42cfec87ddeceb69 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 17:44:24 +0100 Subject: [PATCH 235/303] merge from devel1 --- gcc/config/m68k/amigaos.opt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index 9c08ba43196e..d87f884f06b3 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -45,4 +45,19 @@ Specify startup binary fbbb= Target RejectNegative Report Var(string_bbb_opts) Joined --fbbb=\t\tEnable Bebbo's optimizations. Default: -fbbb=+\n valid letters:\n\t\t+\t\tenable all\n\t\t-\t\tdisable all\n\t\ta\t\tadd move optimization\n\t\tc\t\tcompare to sub\n\t\te\t\teliminate dead assignments\n\t\tf\t\tshrink stack frame\n\t\tm\t\tmerge add statements\n\t\tp\t\tpropagate move pairs from loops\n\t\tr\t\tadditional reg rename pass\n\t\tv\t\tbe verbose\n\t\tx or X\t\tdump insns +-fbbb=Enable Bebbo's optimizations. ++ enable all optimizations +a commute add move instructions +b use register for base addresses +c convert load const and compare into a sub +e eliminate dead assignments + redundant loads +f shrink stack frame +i use post increment on addresses +m merge add and move statements +p propagate move assignment pairs out of loops +r register renaming to maybe save registers +s a strcpy optimization +v be verbose +V be very verbose +x dump insns +Default: -fbbb=+ From 8e8fcc48b69e50a83cf222e5a0166953d6bd7cbd Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 14 Nov 2017 23:30:53 +0100 Subject: [PATCH 236/303] fix def flag in pre-/post-inc, disable elimination for DI --- gcc/DATESTAMP | 2 +- gcc/bbb-opts.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c4335f1aad48..034f28535909 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171011-233828 +20171114-232732 diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ca6e2acadf4d..29a70640b83f 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1056,8 +1056,8 @@ insn_info::scan_rtx (rtx x) } } - if (code == CLOBBER) - def |= use; + if (code == POST_INC || code == PRE_DEC || code == CLOBBER) + def |= myuse; } void @@ -3704,9 +3704,6 @@ track_regs () ii.mark_visited (); ii.get_track_var ()->assign (track); - if (ii.is_compare ()) - continue; - int dregno = ii.get_dst_regno (); unsigned def = ii.get_def (); if (def) @@ -3722,6 +3719,9 @@ track_regs () track->set(dregno, index, 0, index); } + if (ii.is_compare ()) + continue; + if (ii.is_call ()) continue; @@ -3799,7 +3799,7 @@ opt_elim_dead_assign (int blocked_regno) if (!set) continue; - if (ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index)) + if (ii.get_dst_reg () && REG_NREGS(ii.get_dst_reg ()) == 1 && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index)) { log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]); SET_INSN_DELETED(insn); From 11411a654f5ca127ba1fa43615ec543052d72cc4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 15 Nov 2017 21:26:02 +0100 Subject: [PATCH 237/303] refs #3 - forbid pea for baserel expressions inside plus --- gcc/config/m68k/amigaos.h | 10 ---------- gcc/config/m68k/m68k.md | 2 +- gcc/config/m68k/m68kamigaos.h | 10 ++++++++++ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 688f04e37ebb..d8b64576ef47 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -456,16 +456,6 @@ while (0) bool amigaos_rtx_costs (rtx, machine_mode, int, int, int *, bool); -/* SBF: macro to test for const via pic_reg. */ -#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \ - (GET_CODE(x) == CONST \ - && GET_CODE(XEXP(x, 0)) == PLUS \ - && REG_P(XEXP(XEXP(x, 0), 0)) \ - && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \ - && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \ - && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ - ) - #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX amigaos_struct_value_rtx rtx diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index c9ea341789f4..71a54cededeb 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -1566,7 +1566,7 @@ (define_insn "pushasi" [(set (match_operand:SI 0 "push_operand" "=m") (match_operand:SI 1 "address_operand" "p"))] - "" + "(flag_pic < 3) || GET_CODE(operands[1]) != PLUS || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(operands[1], 0))" "pea %a1" [(set_attr "type" "pea")]) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 7dc0e57f5cdc..cd099997bf07 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -755,3 +755,13 @@ extern int amiga_is_const_pic_ref(const_rtx x); extern int amigaos_function_arg_reg(unsigned regno); + +/* SBF: macro to test for const via pic_reg. */ +#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \ + (GET_CODE(x) == CONST \ + && GET_CODE(XEXP(x, 0)) == PLUS \ + && REG_P(XEXP(XEXP(x, 0), 0)) \ + && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \ + && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \ + && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ + ) From 6f8c5e9a1995a1fbb15272251bfb15019486c053 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 15 Nov 2017 21:26:30 +0100 Subject: [PATCH 238/303] update version --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 034f28535909..b8b68f869e68 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171114-232732 +20171115-212610 From b840b61ba578ffe6e2d06b7ce8106ce6a5308f68 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 16 Nov 2017 18:47:33 +0100 Subject: [PATCH 239/303] fix auto_inc fixups --- gcc/bbb-opts.c | 101 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 29a70640b83f..9770b93819e3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -913,23 +913,41 @@ insn_info::auto_inc_fixup (int regno, int size) else XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size); } - else + else if (get_src_mem_regno () == regno) { - rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); - // goto mem if there is an op - if (get_src_mem_regno () == regno && src_op) - mem = XEXP(mem, 1); + // src mem used ? + rtx mem = SET_SRC(set); + if (src_op) + { + if (MEM_P(XEXP(mem, 0))) + mem = XEXP(mem, 0); + else + mem = XEXP(mem, 1); + } + rtx plus = XEXP(mem, 0); + + if (src_mem_addr == (unsigned) size) + { + XEXP(mem, 0) = XEXP(plus, 0); + src_mem_addr = 0; + src_plus = false; + } + else + XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), src_mem_addr -= size); + } + if (get_dst_mem_regno () == regno) + { + rtx mem = SET_DEST(set); rtx plus = XEXP(mem, 0); - if ((get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) == (unsigned) size) + if (dst_mem_addr == (unsigned) size) { XEXP(mem, 0) = XEXP(plus, 0); - (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) = 0; - (get_dst_mem_regno () == regno ? dst_plus : src_plus) = false; + dst_mem_addr = 0; + dst_plus = false; } else - XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), - (get_dst_mem_regno () == regno ? dst_mem_addr : src_mem_addr) -= size); + XEXP(plus, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(plus, 1)), dst_mem_addr -= size); } rtx pattern = add_clobbers (insn); @@ -4019,7 +4037,7 @@ opt_absolute (void) static int try_auto_inc (unsigned index, insn_info & ii, rtx reg) { - int regno = REGNO(reg); + int const regno = REGNO(reg); unsigned size = GET_MODE_SIZE(ii.get_mode ()); if (size > 4) return 0; @@ -4034,18 +4052,14 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) todo.push_back (index + 1); bool match_size = false; - bool ok = true; std::set visited; - while (ok && todo.size () > 0) + while (todo.size () > 0) { unsigned pos = todo[todo.size () - 1]; todo.pop_back (); if (pos == index) - { - ok = false; - break; - } + return 0; if (visited.find (pos) != visited.end ()) continue; @@ -4063,13 +4077,8 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) { insn_info * ll = insn2info.find (j->second)->second; if (ll->is_use (regno)) - { - ok = false; - break; - } + return 0; } - if (ok) - continue; break; } @@ -4078,10 +4087,7 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) break; if (jj.in_proepi ()) - { - ok = false; - break; - } + return 0; // add all labels if (jj.is_jump ()) @@ -4097,52 +4103,45 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) // can't fixup such kind of insn (yet) if (single_set (jj.get_insn ()) == 0) - { - ok = false; - break; - } + return 0; + // if reg is src reg, op must be add and addend must be large enough - if (jj.get_src_regno () == regno || jj.get_src_mem_regno () == regno) + bool fix = false; + if (jj.get_src_mem_regno () == regno) { - if (jj.get_src_mem_addr () < size || (jj.get_dst_mem_regno () == regno && jj.get_dst_mem_addr () < size)) - { - ok = false; - break; - } + if (jj.get_src_mem_addr () < size) + return 0; if (jj.get_src_mem_addr () == size) match_size = true; - fixups.insert (pos); + fix = true; } - else if (jj.get_dst_mem_regno () == regno) + if (jj.get_dst_mem_regno () == regno) { if (jj.get_dst_mem_addr () < size) - { - ok = false; - break; - } + return 0; if (jj.get_dst_mem_addr () == size) match_size = true; - fixups.insert (pos); - } - else - { - ok = false; - break; + fix = true; } + if (!fix) + return 0; + + fixups.insert (pos); + // done if this is an add if (ii.is_def (regno)) break; } } - if (!ok || !match_size || !fixups.size ()) - return 0;; + if (!match_size || !fixups.size ()) + return 0; if (!ii.make_post_inc (regno)) return 0; From a22dcf21bd29bb611cffba71f44be8bd8e374369 Mon Sep 17 00:00:00 2001 From: fautomat Date: Fri, 17 Nov 2017 10:32:33 +0100 Subject: [PATCH 240/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index b8b68f869e68..c6989ab7bfaf 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171115-212610 +20171117-102900 From 74fc8f7c5229526dcbeae19fc50276c872652706 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 17 Nov 2017 23:16:16 +0100 Subject: [PATCH 241/303] modified reg tracking --- gcc/bbb-opts.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 9770b93819e3..294959ecb283 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -144,14 +144,20 @@ class track_var } unsigned get_index(unsigned regno) const { + if (regno >= FIRST_PSEUDO_REGISTER) + return 0; return indexes[regno]; } rtx get_value(unsigned regno) const { + if (regno >= FIRST_PSEUDO_REGISTER) + return 0; return values[regno]; } unsigned get_version(unsigned regno) const { + if (regno >= FIRST_PSEUDO_REGISTER) + return 0; return versions[regno]; } @@ -169,8 +175,7 @@ class track_var { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - indexes[i] = at; - if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i])) + if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i])) values[i] = o->values[i] = 0; } } @@ -181,7 +186,7 @@ class track_var { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - if (versions[i] != o->versions[0] || !values[i] || !o->values[i] || !rtx_equal_p (values[i], o->values[i])) + if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i])) if (values[i]) return false; } @@ -3723,13 +3728,13 @@ track_regs () ii.get_track_var ()->assign (track); int dregno = ii.get_dst_regno (); - unsigned def = ii.get_def (); + unsigned def = ii.get_def () & 0xffffff; if (def) { for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) { // register changed or used somehow - if ( ((1 << regno) & def) || (infos[track->get_index(regno)].get_myuse() & def)) + if ( ((1 << regno) & def) || (track->get_index(regno) && (infos[track->get_index(regno)].get_myuse() & def))) track->set(regno, index, 0, index); } // clear on self update @@ -3827,13 +3832,19 @@ opt_elim_dead_assign (int blocked_regno) // check for redundant load if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno - && !ii.is_use (ii.get_dst_regno ())) + && !ii.is_myuse (ii.get_dst_regno ())) { track_var * track = ii.get_track_var(); + +// if (ii.get_src_regno() == 8 && ii.get_dst_regno() == 7) +// printf("%d: move %d,%d: v=%d (%d->%d), i=%d (%d->%d)\n", index, ii.get_src_regno(), ii.get_dst_regno(), +// track->get_version(ii.get_src_regno()), infos[track->get_version(ii.get_src_regno())].get_src_regno(), infos[track->get_version(ii.get_src_regno())].get_dst_regno(), +// track->get_index(ii.get_dst_regno()), infos[track->get_index(ii.get_dst_regno())].get_src_regno(), infos[track->get_index(ii.get_dst_regno())].get_dst_regno()); + rtx src = SET_SRC(set); if (rtx_equal_p(track->get_value(ii.get_dst_regno()), src)) { - if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(REGNO(src))) + if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(ii.get_src_regno())) || !REG_P(src)) { log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); @@ -3842,6 +3853,18 @@ opt_elim_dead_assign (int blocked_regno) continue; } } + // check reverse assignment + if (REG_P(src)) + { + if (REG_P(src) && rtx_equal_p(track->get_value(ii.get_src_regno()), SET_DEST(set)) + && track->get_version(ii.get_src_regno()) == track->get_index(ii.get_dst_regno())) + { + log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; + } + } } } return change_count; @@ -4308,10 +4331,10 @@ namespace if (do_merge_add && opt_merge_add ()) done = 0; - if (do_absolute && opt_absolute ()) + if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM)) done = 0, update_insns (); - if (do_elim_dead_assign && opt_elim_dead_assign (STACK_POINTER_REGNUM)) + if (do_absolute && opt_absolute ()) done = 0, update_insns (); if (do_autoinc && opt_autoinc ()) From 7f672ad9e54bd8fc4cc1d13cac737374412481aa Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 18 Nov 2017 16:16:38 +0100 Subject: [PATCH 242/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c6989ab7bfaf..53f5062dcd68 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171117-102900 +20171118-161638 From b4f98bfecd75e74c6f488a8c2dd25b825bcb9c13 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 19 Nov 2017 12:45:24 +0100 Subject: [PATCH 243/303] improved function type checking for __regargs, __stdargs and asm register parameters --- gcc/c/c-decl.c | 29 ++++++++++++++++++-- gcc/config/m68k/amigaos.c | 70 +++++++++++++++++++++++++++++++++-------------- gcc/config/m68k/amigaos.h | 9 +++--- 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index b0df4e1d9a65..42ebfeb9fa90 100644 --- gcc/c/c-decl.c +++ gcc/c/c-decl.c @@ -4441,7 +4441,32 @@ c_decl_attributes (tree *node, tree attributes, int flags) attributes = tree_cons (get_identifier ("omp declare target"), NULL_TREE, attributes); } - return decl_attributes (node, attributes, flags); + + tree returned_attrs = decl_attributes (node, attributes, flags); + +#ifdef TARGET_AMIGA + /* add an attribute to the function decl's type if there are asm register parameters. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + { + char * synthetic = ""; + for (tree params = TYPE_ARG_TYPES(TREE_TYPE(*node)); params; params = TREE_CHAIN(params)) + { + tree asmattr = lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(params))); + if (asmattr) + synthetic = concat(synthetic, reg_names[TREE_FIXED_CST_PTR(TREE_VALUE(asmattr))->data.low], 0); + } + if (strlen(synthetic) > 0) + { + tree asmid = get_identifier("asmregs"); + tree syntheticid = get_identifier(synthetic); + tree newattr = tree_cons(asmid, syntheticid, NULL_TREE); + + TYPE_ATTRIBUTES(TREE_TYPE(*node)) = chainon(newattr, TYPE_ATTRIBUTES(TREE_TYPE(*node))); + } + } +#endif + + return returned_attrs; } @@ -5114,7 +5139,7 @@ push_parm_decl (const struct c_parm *parm, tree *expr) TYPE_ATTRIBUTES(atype) = chainon (attrs, TYPE_ATTRIBUTES(atype)); } TREE_TYPE(decl) = atype; -// printf("%s using %s, cdecl=%p, type=%p\n", IDENTIFIER_POINTER(DECL_NAME (decl), asmspec, decl, atype); +// printf("%s using %s, cdecl=%p, type=%p\n", IDENTIFIER_POINTER(DECL_NAME (decl)), asmspec, decl, atype); } } #endif diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 53e01499341d..991c2905668f 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -393,7 +393,7 @@ amigaos_init_cumulative_args (CUMULATIVE_ARGS *cump, tree fntype, tree decl) if (fntype) { - tree attrs = decl ? DECL_ATTRIBUTES(decl) : NULL; + tree attrs = TYPE_ATTRIBUTES(fntype); if (attrs) { if (lookup_attribute ("stkparm", attrs)) @@ -622,27 +622,57 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2) ways of passing arguments. */ if (TREE_CODE(type1) == FUNCTION_TYPE || TREE_CODE(type1) == METHOD_TYPE) { - tree arg1, arg2; - arg1 = TYPE_ARG_TYPES(type1); - arg2 = TYPE_ARG_TYPES(type2); - for (; arg1 && arg2; arg1 = TREE_CHAIN(arg1), arg2 = TREE_CHAIN(arg2)) + tree attrs1 = TYPE_ATTRIBUTES(type1); + + tree asm1 = lookup_attribute("asmregs", attrs1); + tree stack1 = lookup_attribute("stkparm", attrs1); + tree reg1 = lookup_attribute("regparm", attrs1); + + tree attrs2 = TYPE_ATTRIBUTES(type2); + + tree asm2 = lookup_attribute("asmregs", attrs2); + tree stack2 = lookup_attribute("stkparm", attrs2); + tree reg2 = lookup_attribute("regparm", attrs2); + + if (reg1) { - tree attr1 = TYPE_ATTRIBUTES(arg1); - tree attr2 = TYPE_ATTRIBUTES(arg2); - if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr1)))) - attr1 = NULL_TREE; - if (strcmp ("asm", IDENTIFIER_POINTER(TREE_PURPOSE(attr2)))) - attr2 = NULL_TREE; - if (attr1 && attr2) - { - if (TREE_FIXED_CST_PTR(TREE_VALUE(attr1))->data.low != TREE_FIXED_CST_PTR(TREE_VALUE(attr2))->data.low) - return 0; - } - else if (attr1 || attr2) - return 0; /* asm attribute only on one side. */ + if (stack2 || asm2) + return 0; + + int no1 = TREE_INT_CST_LOW(TREE_VALUE(reg1)); + int no2 = reg2 ? TREE_INT_CST_LOW(TREE_VALUE(reg2)) : amigaos_regparm; + return no1 == no2; + } + + if (reg2) + { + if (stack1 || asm1) + return 0; + + int no2 = TREE_INT_CST_LOW(TREE_VALUE(reg2)); + return amigaos_regparm == no2; + } + + if (stack1) { + if (stack2) + return 1; + return amigaos_regparm == 0; + } + + if (stack2) + return amigaos_regparm == 0; + + if (asm1) + { + if (!asm2) + return 0; + + return 0 == strcmp(IDENTIFIER_POINTER(TREE_VALUE(asm1)), IDENTIFIER_POINTER(TREE_VALUE(asm2))); } - if (arg1 || arg2) - return 0; /* different count of parameters. */ + + if (asm2) + return 0; + } return 1; } diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index d8b64576ef47..11dd88854160 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -444,10 +444,11 @@ while (0) /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, affects_type_identity } */ #define SUBTARGET_ATTRIBUTES \ - { "regparm", 1, 1, true, false, false, amigaos_handle_type_attribute,\ - false }, \ - { "stkparm", 0, 0, true, false, false, amigaos_handle_type_attribute,\ - false }, + { "asmregs", 0, 0, false, false, false, 0, true }, \ + { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\ + true }, \ + { "stkparm", 0, 0, false, true, true, amigaos_handle_type_attribute,\ + true }, #define GOT_SYMBOL_NAME "" From 16411f7189d41024a5dc0b3a171b519e9295ee94 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 19 Nov 2017 12:56:25 +0100 Subject: [PATCH 244/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 53f5062dcd68..833a789eb3c6 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171118-161638 +20171119-125625 From 5d5c1d671aef73f71094976d17cd54a709582274 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 20 Nov 2017 09:55:01 +0100 Subject: [PATCH 245/303] refs #3 - block an invalid combined insn --- gcc/config/m68k/amigaos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 991c2905668f..b65059edf2fa 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -941,7 +941,7 @@ amigaos_legitimate_combined_insn (rtx_insn * insn) return true; x = XEXP(x, 0); - if (GET_CODE(x) != NOT) + if (GET_CODE(x) != NOT && GET_CODE(x) != NEG) return true; x = XEXP(x, 0); From ca2ff3994ec1def3da8e9df51c0e80614c304784 Mon Sep 17 00:00:00 2001 From: fautomat Date: Mon, 20 Nov 2017 16:07:27 +0100 Subject: [PATCH 246/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 833a789eb3c6..0e38b8ced4de 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171119-125625 +20171120-160727 From 06d2e5b1b649b8f64333cdab447c70df3eb22ee9 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Nov 2017 19:31:46 +0100 Subject: [PATCH 247/303] refs #3 - added workarounds for baserel modes added an additional pass to convert combined baserel insns into correct form fixed peephole optimizer to leave pea insns untouched --- gcc/bbb-opts.c | 179 +++++++++++++++++++++++++++++++++++------ gcc/config/m68k/constraints.md | 2 +- gcc/config/m68k/m68k.md | 4 +- gcc/passes.c | 10 +-- gcc/passes.def | 1 + gcc/recog.c | 12 +++ gcc/tree-pass.h | 1 + 7 files changed, 175 insertions(+), 34 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 294959ecb283..a4fee5f446b0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -143,19 +143,25 @@ class track_var versions[regno] = ver; } - unsigned get_index(unsigned regno) const { + unsigned + get_index (unsigned regno) const + { if (regno >= FIRST_PSEUDO_REGISTER) return 0; return indexes[regno]; } - rtx get_value(unsigned regno) const { + rtx + get_value (unsigned regno) const + { if (regno >= FIRST_PSEUDO_REGISTER) return 0; return values[regno]; } - unsigned get_version(unsigned regno) const { + unsigned + get_version (unsigned regno) const + { if (regno >= FIRST_PSEUDO_REGISTER) return 0; return versions[regno]; @@ -948,7 +954,7 @@ insn_info::auto_inc_fixup (int regno, int size) if (dst_mem_addr == (unsigned) size) { XEXP(mem, 0) = XEXP(plus, 0); - dst_mem_addr = 0; + dst_mem_addr = 0; dst_plus = false; } else @@ -3029,7 +3035,7 @@ track_sp () // if sp is used as source, we cannot shrink the stack yet // too complicated - if (ii.get_src_regno() == STACK_POINTER_REGNUM) + if (ii.get_src_regno () == STACK_POINTER_REGNUM) return -1; } @@ -3699,13 +3705,12 @@ track_regs () track_var * const track = todo.begin ()->second; todo.erase (todo.begin ()); - for (unsigned index = startpos; index < infos.size (); ++index) { insn_info & ii = infos[index]; // already visited? - if (index != startpos && ii.is_visited () && ii.get_track_var ()->no_merge_needed(track)) + if (index != startpos && ii.is_visited () && ii.get_track_var ()->no_merge_needed (track)) break; // only keep common values at labels @@ -3734,12 +3739,13 @@ track_regs () for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) { // register changed or used somehow - if ( ((1 << regno) & def) || (track->get_index(regno) && (infos[track->get_index(regno)].get_myuse() & def))) - track->set(regno, index, 0, index); + if (((1 << regno) & def) + || (track->get_index (regno) && (infos[track->get_index (regno)].get_myuse () & def))) + track->set (regno, index, 0, index); } // clear on self update - if (def & ii.get_myuse()) - track->set(dregno, index, 0, index); + if (def & ii.get_myuse ()) + track->set (dregno, index, 0, index); } if (ii.is_compare ()) @@ -3760,7 +3766,7 @@ track_regs () todo.insert (std::make_pair (i->second, new track_var (track))); if (set && GET_CODE(SET_SRC(set)) == IF_THEN_ELSE) - continue; + continue; // unconditional jump break; @@ -3784,17 +3790,17 @@ track_regs () unsigned version; if (GET_CODE(src) != CONST_INT && GET_CODE(src) != CONST_FIXED && GET_CODE(src) != CONST_DOUBLE) { - if (ii.get_src_regno() >= 0) - version = track->get_index(ii.get_src_regno()); - else if (ii.get_src_mem_regno() >= 0) - version = track->get_index(ii.get_src_mem_regno()); + if (ii.get_src_regno () >= 0) + version = track->get_index (ii.get_src_regno ()); + else if (ii.get_src_mem_regno () >= 0) + version = track->get_index (ii.get_src_mem_regno ()); else version = index; } else version = 0; - track->set(dregno, index, src, version); + track->set (dregno, index, src, version); } delete track; } @@ -3822,7 +3828,8 @@ opt_elim_dead_assign (int blocked_regno) if (!set) continue; - if (ii.get_dst_reg () && REG_NREGS(ii.get_dst_reg ()) == 1 && ii.get_dst_regno () != blocked_regno && is_reg_dead (ii.get_dst_regno (), index)) + if (ii.get_dst_reg () && REG_NREGS(ii.get_dst_reg ()) == 1 && ii.get_dst_regno () != blocked_regno + && is_reg_dead (ii.get_dst_regno (), index)) { log ("(e) %d: eliminate dead assign to %s\n", index, reg_names[ii.get_dst_regno ()]); SET_INSN_DELETED(insn); @@ -3834,7 +3841,7 @@ opt_elim_dead_assign (int blocked_regno) if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno && !ii.is_myuse (ii.get_dst_regno ())) { - track_var * track = ii.get_track_var(); + track_var * track = ii.get_track_var (); // if (ii.get_src_regno() == 8 && ii.get_dst_regno() == 7) // printf("%d: move %d,%d: v=%d (%d->%d), i=%d (%d->%d)\n", index, ii.get_src_regno(), ii.get_dst_regno(), @@ -3842,9 +3849,9 @@ opt_elim_dead_assign (int blocked_regno) // track->get_index(ii.get_dst_regno()), infos[track->get_index(ii.get_dst_regno())].get_src_regno(), infos[track->get_index(ii.get_dst_regno())].get_dst_regno()); rtx src = SET_SRC(set); - if (rtx_equal_p(track->get_value(ii.get_dst_regno()), src)) + if (rtx_equal_p (track->get_value (ii.get_dst_regno ()), src)) { - if ((REG_P(src) && track->get_version(ii.get_dst_regno()) == track->get_index(ii.get_src_regno())) + if ((REG_P(src) && track->get_version (ii.get_dst_regno ()) == track->get_index (ii.get_src_regno ())) || !REG_P(src)) { log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); @@ -3856,8 +3863,8 @@ opt_elim_dead_assign (int blocked_regno) // check reverse assignment if (REG_P(src)) { - if (REG_P(src) && rtx_equal_p(track->get_value(ii.get_src_regno()), SET_DEST(set)) - && track->get_version(ii.get_src_regno()) == track->get_index(ii.get_dst_regno())) + if (REG_P(src) && rtx_equal_p (track->get_value (ii.get_src_regno ()), SET_DEST(set)) + && track->get_version (ii.get_src_regno ()) == track->get_index (ii.get_dst_regno ())) { log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); SET_INSN_DELETED(insn); @@ -4128,7 +4135,6 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) if (single_set (jj.get_insn ()) == 0) return 0; - // if reg is src reg, op must be add and addend must be large enough bool fix = false; if (jj.get_src_mem_regno () == regno) @@ -4379,3 +4385,128 @@ make_pass_bbb_optimizations (gcc::context * ctxt) { return new pass_bbb_optimizations (ctxt); } + +namespace +{ + + const pass_data pass_data_bbb_baserel = + { RTL_PASS, /* type */ + "bebbo's-baserel fixer", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_NONE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, //( TODO_df_finish | TODO_df_verify), /* todo_flags_finish */ + }; + + class pass_bbb_baserel : public rtl_opt_pass + { + public: + pass_bbb_baserel (gcc::context *ctxt) : + rtl_opt_pass (pass_data_bbb_baserel, ctxt), pp (0) + { + } + + /* opt_pass methods: */ + virtual bool + gate (function *) + { + return TARGET_AMIGA && flag_pic >= 3; + } + + virtual unsigned int + execute (function *) + { + return execute_bbb_baserel (); + } + + opt_pass * + clone () + { + pass_bbb_baserel * bbb = new pass_bbb_baserel (m_ctxt); + return bbb; + } + + unsigned int pp; + + unsigned + execute_bbb_baserel (void); + }; +// class pass_bbb_optimizations + + /* Main entry point to the pass. */ + unsigned + pass_bbb_baserel::execute_bbb_baserel (void) + { + rtx_insn *insn, *next; + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + + if (NONJUMP_INSN_P(insn)) + { + rtx set = single_set (insn); + if (!set) + continue; + + rtx * src = &SET_SRC(set); + if (MEM_P(*src)) + src = &XEXP(*src, 0); + + bool ispicref = false; + // fix add PLUS/MINUS into the unspec offset + if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS) + { + if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0))) + { + bool isplus = GET_CODE(*src) == PLUS; + rtx offset = XEXP(*src, 1); + + // unlink PLUS/MINUS + *src = XEXP(*src, 0); + + rtx plus = XEXP(*src, 0); + rtx cnst = XEXP(plus, 1); + rtx unspec = XEXP(cnst, 0); + + XVECEXP(unspec, 0, 0) = gen_rtx_PLUS(SImode, XVECEXP(unspec, 0, 0), gen_rtx_CONST_INT (SImode, isplus ? INTVAL(offset) : -INTVAL(offset))); + + ispicref = true; + } + } + else + ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(*src); + + if (ispicref) + { + rtx dest = SET_DEST(set); + if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC + ) + { + // split the insn + rtx reg = gen_reg_rtx (Pmode); + + rtx pat0 = gen_rtx_SET(reg, *src); + rtx_insn * n0 = emit_insn_before(pat0, insn); + + rtx pat1 = gen_rtx_SET(dest, reg); + rtx_insn * n1 = emit_insn_before(pat1, insn); + + SET_INSN_DELETED(insn); + } + } + } + } + + return 0; + } + +} // anon namespace + +rtl_opt_pass * +make_pass_bbb_baserel (gcc::context * ctxt) +{ + return new pass_bbb_baserel (ctxt); +} diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md index 94a785dc95b6..0d9b1b69ab18 100644 --- gcc/config/m68k/constraints.md +++ gcc/config/m68k/constraints.md @@ -101,7 +101,7 @@ "Used for operands that satisfy 's' without PIC stuff, when -mpcrel is not in effect." (and (match_code "symbol_ref,label_ref,const") (match_test "!TARGET_PCREL") - (match_test "!flag_pic || GET_CODE(op) != CONST || GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF"))) + (match_test "!flag_pic || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(op)"))) (define_memory_constraint "Q" "Means address register indirect addressing mode." diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 71a54cededeb..906fde496031 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -1564,9 +1564,9 @@ ;; so we will prefer it to them. (define_insn "pushasi" - [(set (match_operand:SI 0 "push_operand" "=m") + [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "address_operand" "p"))] - "(flag_pic < 3) || GET_CODE(operands[1]) != PLUS || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(operands[1], 0))" + "" "pea %a1" [(set_attr "type" "pea")]) diff --git a/gcc/passes.c b/gcc/passes.c index 321adbc61e2d..407160f4e4d6 100644 --- gcc/passes.c +++ gcc/passes.c @@ -2276,18 +2276,14 @@ void dump_insns(char const * name) for (insn = get_insns(); insn; insn = next) { next = NEXT_INSN(insn); - debug_rtx(insn); -#if 0 +#if 1 if (NONJUMP_INSN_P (insn)) { - rtx x, y, set= single_set (insn); + rtx set= single_set (insn); if (!set) continue; - x = y = SET_SRC(set); - while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS) - y = XEXP(y, 0); - if (x != y && REG_P(y) && REGNO(y) == PIC_REG) + if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set)) && MEM_P(SET_DEST(set))) debug_rtx(insn); } #endif diff --git a/gcc/passes.def b/gcc/passes.def index 6af49b56fb03..61d0e4d47377 100644 --- gcc/passes.def +++ gcc/passes.def @@ -386,6 +386,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_gen_hsail); NEXT_PASS (pass_expand); + NEXT_PASS (pass_bbb_baserel); NEXT_PASS (pass_rest_of_compilation); PUSH_INSERT_PASSES_WITHIN (pass_rest_of_compilation) diff --git a/gcc/recog.c b/gcc/recog.c index 92b2aa31a777..1b215f350fd6 100644 --- gcc/recog.c +++ gcc/recog.c @@ -3249,9 +3249,21 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt) rtx_insn *new_insn; bool was_call = false; +#ifdef TARGET_AMIGA + /* SBF: splitting may yield invalid insns -> avoid it for the special pea insn! */ + for (int i = 0; i <= match_len; ++i) + { + rtx_insn * insn0 = peep2_insn_data[i].insn; + rtx set0 = single_set(insn0); + if (set0 && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set0)) && MEM_P(SET_DEST(set0))) + return 0; + } +#endif + /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to match more than one insn, or to be split into more than one insn. */ old_insn = peep2_insn_data[peep2_current].insn; + if (RTX_FRAME_RELATED_P (old_insn)) { bool any_note = false; diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index b3f66ad529b9..76c0996850f4 100644 --- gcc/tree-pass.h +++ gcc/tree-pass.h @@ -591,6 +591,7 @@ extern rtl_opt_pass *make_pass_branch_target_load_optimize2 (gcc::context extern rtl_opt_pass *make_pass_leaf_regs (gcc::context *ctxt); extern rtl_opt_pass *make_pass_split_before_sched2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_bbb_optimizations (gcc::context *ctxt); +extern rtl_opt_pass *make_pass_bbb_baserel (gcc::context *ctxt); extern rtl_opt_pass *make_pass_compare_elim_after_reload (gcc::context *ctxt); extern rtl_opt_pass *make_pass_sched2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_stack_regs (gcc::context *ctxt); From 4032d56eb771309d6aac6cbee68ce0bd2412e3e4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 23 Nov 2017 20:18:51 +0100 Subject: [PATCH 248/303] refs #3 fix npe if pattern == 0 --- gcc/recog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/recog.c b/gcc/recog.c index 1b215f350fd6..de2340518e52 100644 --- gcc/recog.c +++ gcc/recog.c @@ -3254,6 +3254,8 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt) for (int i = 0; i <= match_len; ++i) { rtx_insn * insn0 = peep2_insn_data[i].insn; + if (!PATTERN(insn0)) + continue; rtx set0 = single_set(insn0); if (set0 && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set0)) && MEM_P(SET_DEST(set0))) return 0; From 6c1e4ac7b3e47db3795aecf5780244bd2d3f86a1 Mon Sep 17 00:00:00 2001 From: fautomat Date: Thu, 23 Nov 2017 20:35:57 +0100 Subject: [PATCH 249/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 0e38b8ced4de..a3ce57172f94 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171120-160727 +20171123-203556 From 89ee14d7bf65457e1b5e7f0f4f02d2e36dd31296 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Nov 2017 19:53:48 +0100 Subject: [PATCH 250/303] print the invalid insn if invalid expression as operand --- gcc/final.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/final.c b/gcc/final.c index 420ac2b08fa1..009d8eca6baf 100644 --- gcc/final.c +++ gcc/final.c @@ -4002,6 +4002,7 @@ output_addr_const (FILE *file, rtx x) if (targetm.asm_out.output_addr_const_extra (file, x)) break; + debug_rtx(current_output_insn); output_operand_lossage ("invalid expression as operand"); } } From 6d7603c860ea47e19102eabe262c7cd34d7ab304 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Nov 2017 19:54:52 +0100 Subject: [PATCH 251/303] use the default include folder (was non existant os-include) --- gcc/config/m68k/m68kamigaos.h | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index cd099997bf07..0e982c12da9c 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -686,22 +686,8 @@ amigaos_prelink_hook((const char **)(LD1_ARGV), (STRIP)) #undef MAX_OFILE_ALIGNMENT #define MAX_OFILE_ALIGNMENT ((1 << 15)*BITS_PER_UNIT) -#if 0 -#undef INCLUDE_DEFAULTS -#define INCLUDE_DEFAULTS \ - { \ - { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \ - GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \ - { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \ - { CROSS_INCLUDE_DIR "/../../os-include", "GCC", 0, 0 }, \ - { TOOL_INCLUDE_DIR "/../ndk/include", "GCC", 0, 0 }, \ - { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 }, \ - { 0, 0, 0, 0 } \ - } -#endif - #undef FIXED_INCLUDE_DIR -#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../os-include" +#define FIXED_INCLUDE_DIR CROSS_INCLUDE_DIR "/../../include" // this disables tree_loop_distribute_patterns #define C_COMMON_OVERRIDE_OPTIONS flag_no_builtin = 1 From e25ebad9d63114a43b258f2045c646b8b090ebee Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Nov 2017 20:39:19 +0100 Subject: [PATCH 252/303] fixed warnings --- gcc/c/c-decl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 42ebfeb9fa90..642829b828c7 100644 --- gcc/c/c-decl.c +++ gcc/c/c-decl.c @@ -4448,12 +4448,12 @@ c_decl_attributes (tree *node, tree attributes, int flags) /* add an attribute to the function decl's type if there are asm register parameters. */ if (TREE_CODE (*node) == FUNCTION_DECL) { - char * synthetic = ""; + char const * synthetic = ""; for (tree params = TYPE_ARG_TYPES(TREE_TYPE(*node)); params; params = TREE_CHAIN(params)) { tree asmattr = lookup_attribute("asm", TYPE_ATTRIBUTES(TREE_VALUE(params))); if (asmattr) - synthetic = concat(synthetic, reg_names[TREE_FIXED_CST_PTR(TREE_VALUE(asmattr))->data.low], 0); + synthetic = concat(synthetic, reg_names[TREE_FIXED_CST_PTR(TREE_VALUE(asmattr))->data.low], NULL); } if (strlen(synthetic) > 0) { From 6dda10eb7bc66196a2e359d87dc9c832eed982f1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Nov 2017 20:40:33 +0100 Subject: [PATCH 253/303] added checks to prevent invalid baserel insns plus some converions into valid insns for better code --- gcc/bbb-opts.c | 16 +-- gcc/config/m68k/amigaos-protos.h | 3 +- gcc/config/m68k/amigaos.c | 281 ++++++++++++++++++++------------------- gcc/config/m68k/amigaos.h | 41 ++++-- gcc/config/m68k/m68k.c | 21 ++- 5 files changed, 193 insertions(+), 169 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index a4fee5f446b0..2d3280230207 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -4461,19 +4461,7 @@ namespace { if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0))) { - bool isplus = GET_CODE(*src) == PLUS; - rtx offset = XEXP(*src, 1); - - // unlink PLUS/MINUS - *src = XEXP(*src, 0); - - rtx plus = XEXP(*src, 0); - rtx cnst = XEXP(plus, 1); - rtx unspec = XEXP(cnst, 0); - - XVECEXP(unspec, 0, 0) = gen_rtx_PLUS(SImode, XVECEXP(unspec, 0, 0), gen_rtx_CONST_INT (SImode, isplus ? INTVAL(offset) : -INTVAL(offset))); - - ispicref = true; + amigaos_add_offset_to_symbol(src); } } else @@ -4482,7 +4470,7 @@ namespace if (ispicref) { rtx dest = SET_DEST(set); - if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC + if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC ) { // split the insn diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h index 97733002f4f9..ce20a17d1840 100644 --- gcc/config/m68k/amigaos-protos.h +++ gcc/config/m68k/amigaos-protos.h @@ -34,8 +34,6 @@ extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree, tree); #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ (amigaos_init_cumulative_args(&(CUM), (FNTYPE), (INDIRECT))) - -extern int amigaos_restore_a4 (void); #ifdef RTX_CODE extern int read_only_operand (rtx); extern void amigaos_select_section (tree, int, unsigned HOST_WIDE_INT); @@ -56,3 +54,4 @@ extern tree amigaos_handle_decl_attribute (tree *, tree, tree, int, bool *); extern tree amigaos_handle_type_attribute (tree *, tree, tree, int, bool *); #endif +extern void amigaos_add_offset_to_symbol(rtx *); diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index b65059edf2fa..9d2fc73d35f3 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -148,26 +148,6 @@ amigaos_encode_section_info (tree decl, rtx rtl, int first) } } -/* Common routine used to check if a4 should be preserved/restored. */ - -int -amigaos_restore_a4 (void) - { - return (flag_pic >= 3 && - (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4 - || lookup_attribute ("saveds", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))); - } - -void -amigaos_alternate_pic_setup (FILE *stream) - { - if (TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) - asm_fprintf (stream, "\tjbsr %U__restore_a4\n"); - else if (lookup_attribute ("saveds", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - asm_fprintf (stream, "\tlea %U__a4_init,%Ra4\n"); - } /* Attributes support. */ @@ -242,53 +222,6 @@ amigaos_prologue_begin_hook (FILE *stream, int fsize) } } -void -amigaos_alternate_frame_setup_f (FILE *stream, int fsize) - { - if (fsize < 128) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I%d,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\tlink %Ra5,%I%d:W\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit")), - fsize, -fsize); - else - asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n", - fsize); - } - -void -amigaos_alternate_frame_setup (FILE *stream, int fsize) - { - if (!fsize) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I0,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit"))); - else if (fsize < 128) - asm_fprintf (stream, "\tcmpl %s,%Rsp\n" - "\tjcc 0f\n" - "\tmoveq %I%d,%Rd0\n" - "\tmoveq %I0,%Rd1\n" - "\tjbsr %U__stkext_f\n" - "0:\taddw %I%d,%Rsp\n", - (flag_pic == 3 ? "a4@(___stk_limit:W)" : - (flag_pic == 4 ? "a4@(___stk_limit:L)" : - "___stk_limit")), - fsize, -fsize); - else - asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n", - fsize); - } //static rtx //gen_stack_management_call (rtx stack_pointer, rtx arg, const char *func) @@ -676,58 +609,9 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2) } return 1; } - -/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible, - one if they are compatible, and two if they are nearly compatible - (which causes a warning to be generated). */ -#if 0 -static int -m68k_comp_type_attributes (tree type1, tree type2) - { - - /* Functions or methods are incompatible if they specify mutually - exclusive ways of passing arguments. */ - if (TREE_CODE (type1) == FUNCTION_TYPE || TREE_CODE (type1) == METHOD_TYPE) - { - tree arg1, arg2; - if (!! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type1)) != - !! lookup_attribute ("stkparm", TYPE_ATTRIBUTES (type2)) - || !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)) != - !! lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2))) - return 0; /* 'regparm' and 'stkparm' are mutually exclusive. */ - - arg1 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type1)); - arg2 = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type2)); - if (arg1 && arg2) - { - int num1 = 0, num2 = 0; - if (TREE_VALUE (arg1) && TREE_CODE (TREE_VALUE (arg1)) == TREE_LIST) - { - tree numofregs = TREE_VALUE (TREE_VALUE (arg1)); - if (numofregs) - num1 = TREE_INT_CST_LOW (numofregs); - } - if (TREE_VALUE (arg2) && TREE_CODE (TREE_VALUE (arg2)) == TREE_LIST) - { - tree numofregs = TREE_VALUE (TREE_VALUE (arg2)); - if (numofregs) - num2 = TREE_INT_CST_LOW (numofregs); - } - if (num1 != num2) - return 0; /* Different numbers, or no number in one type. */ - } - } -#ifdef TARGET_AMIGAOS - return amigaos_comp_type_attributes(type1, type2); -#else - return 1; -#endif - } -#endif - /* end-GG-local */ -/* Handle a "regparm", "stkparm" attribute; +/* Handle a regparm, stkparm, saveds attribute; arguments as in struct attribute_spec.handler. */ tree amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) @@ -915,35 +799,156 @@ amigaos_static_chain_rtx (const_tree decl, bool incoming ATTRIBUTE_UNUSED) return 0; } -/* - * decline src like: -(plus:SI (reg/f:SI 0 d0 [210]) - (const:SI (minus:SI (not:SI (reg:SI 12 a4)) +/** + * Necessary to block some funny invalid combinations if baserel is used: * +(const:SI (minus:SI (neg:SI (reg:SI 12 a4)) + (const:SI (plus:SI (unspec:SI [ + (symbol_ref:SI ("xyz") ) + (const_int 0 [0]) + ] 6) + +(plus:SI (reg:SI 10 a2) + (const:SI (minus:SI (neg:SI (reg:SI 12 a4)) + (const:SI (plus:SI (unspec:SI [ + (symbol_ref:SI ("xyz") ) + (const_int 0 [0]) + ] 6) + (const_int 1234 [0xe00]))))))) xyz.c:41 465 {*lea} + */ bool -amigaos_legitimate_combined_insn (rtx_insn * insn) +amigaos_legitimate_src (rtx src) { - rtx set = single_set(insn); - if (!set) + if (flag_pic < 3) return true; - rtx x = SET_SRC(set); - if (GET_CODE(x) != PLUS) - return true; + if (GET_CODE(src) == PLUS || GET_CODE(src) == MINUS) + { + rtx x = XEXP(src, 0); + if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x)) + { + amigaos_add_offset_to_symbol(&src); + return true; + } - x = XEXP(x, 1); - if (GET_CODE(x) != CONST) - return true; + return amigaos_legitimate_src(x) && amigaos_legitimate_src(XEXP(src, 1)); + } - x = XEXP(x, 0); - if (GET_CODE(x) != MINUS) - return true; + if (GET_CODE(src) == CONST) + { + rtx op = XEXP(src, 0); + if (GET_CODE(op) == MINUS || GET_CODE(op) == PLUS) + { + rtx x = XEXP(op, 0); + if (GET_CODE(x) == NOT || GET_CODE(x) == NEG) + { + rtx reg = XEXP(x, 0); + if (!REG_P(reg)) + return true; - x = XEXP(x, 0); - if (GET_CODE(x) != NOT && GET_CODE(x) != NEG) - return true; +// debug_rtx(src); + return false; + } + } + + if (GET_CODE(op) == UNSPEC) + { +// debug_rtx(src); + return false; + } + } - x = XEXP(x, 0); - return !REG_P(x); + return true; } + +void amigaos_add_offset_to_symbol(rtx * src) +{ + static char num[16]; + bool isplus = GET_CODE(*src) == PLUS; + rtx offset = XEXP(*src, 1); + sprintf(num, "%d", (int)INTVAL(offset)); + + /* unlink PLUS/MINUS */ + *src = XEXP(*src, 0); + + rtx plus = XEXP(*src, 0); + rtx cnst = XEXP(plus, 1); + rtx unspec = XEXP(cnst, 0); + rtx sym = XVECEXP(unspec, 0, 0); + const char * s = XSTR(sym, 0); + + /* create a new symbol containing the offset. */ + const char * t = concat(s, isplus ? "+" : "-", num, NULL); + XVECEXP(unspec, 0, 0) = gen_rtx_SYMBOL_REF(Pmode, t); +} + + +void +amigaos_restore_a4 (void) + { + if (flag_pic >= 3) + { + tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); + tree attr = lookup_attribute ("saveds", attrs); + if (attr || TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) + { + rtx a4 = gen_rtx_ASM_INPUT_loc(VOIDmode, "\tlea ___init_a4,a4", DECL_SOURCE_LOCATION (current_function_decl)); + a4->volatil = 1; + emit_insn(a4); + } + } + } + +void +amigaos_alternate_frame_setup_f (int fsize) + { +#if 0 + if (fsize < 128) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\tlink %Ra5,%I%d:W\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__link_a5_d0_f\n", + fsize); +#endif + } + +void +amigaos_alternate_frame_setup (int fsize) + { +#if 0 + if (!fsize) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I0,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit"))); + else if (fsize < 128) + asm_fprintf (stream, "\tcmpl %s,%Rsp\n" + "\tjcc 0f\n" + "\tmoveq %I%d,%Rd0\n" + "\tmoveq %I0,%Rd1\n" + "\tjbsr %U__stkext_f\n" + "0:\taddw %I%d,%Rsp\n", + (flag_pic == 3 ? "a4@(___stk_limit:W)" : + (flag_pic == 4 ? "a4@(___stk_limit:L)" : + "___stk_limit")), + fsize, -fsize); + else + asm_fprintf (stream, "\tmovel %I%d,%Rd0\n\tjbsr %U__sub_d0_sp_f\n", + fsize); +#endif + } + diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 11dd88854160..fe300515fa5f 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -1,4 +1,7 @@ /* Configuration for GNU C-compiler for m68k Amiga, running AmigaOS. + * + * This file is only included and used inside m68k.c to define the target. + * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003 Free Software Foundation, Inc. Contributed by Markus M. Wild (wild@amiga.physik.unizh.ch). @@ -288,16 +291,6 @@ while (0) #define PROLOGUE_BEGIN_HOOK(STREAM, FSIZE) \ (amigaos_prologue_begin_hook ((STREAM), (FSIZE))) -#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND - -#define ALTERNATE_FRAME_SETUP_F(STREAM, FSIZE) \ - (amigaos_alternate_frame_setup_f ((STREAM), (FSIZE))) - -#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND - -#define ALTERNATE_FRAME_SETUP(STREAM, FSIZE) \ - (amigaos_alternate_frame_setup ((STREAM), (FSIZE))) - #define HAVE_ALTERNATE_FRAME_DESTR_F(FSIZE) \ (TARGET_STACKEXTEND && current_function_calls_alloca) @@ -445,6 +438,7 @@ while (0) affects_type_identity } */ #define SUBTARGET_ATTRIBUTES \ { "asmregs", 0, 0, false, false, false, 0, true }, \ + { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute, false }, \ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\ true }, \ { "stkparm", 0, 0, false, true, true, amigaos_handle_type_attribute,\ @@ -469,7 +463,26 @@ rtx amigaos_static_chain_rtx(const_tree fntype, bool incoming ATTRIBUTE_UNUSED); -#undef TARGET_LEGITIMATE_COMBINED_INSN -#define TARGET_LEGITIMATE_COMBINED_INSN amigaos_legitimate_combined_insn -bool -amigaos_legitimate_combined_insn (rtx_insn *insn ATTRIBUTE_UNUSED); + +extern bool +amigaos_legitimate_src (rtx src); + +extern void +amigaos_restore_a4 (void); + +extern void +amigaos_alternate_frame_setup_f (int fsize); + +extern void +amigaos_alternate_frame_setup (int fsize); + + +#define HAVE_ALTERNATE_FRAME_SETUP_F(FSIZE) TARGET_STACKEXTEND + +#define ALTERNATE_FRAME_SETUP_F(FSIZE) \ + (amigaos_alternate_frame_setup_f ((FSIZE))) + +#define HAVE_ALTERNATE_FRAME_SETUP(FSIZE) TARGET_STACKEXTEND + +#define ALTERNATE_FRAME_SETUP(FSIZE) \ + (amigaos_alternate_frame_setup ((FSIZE))) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index ed9b76caf11d..4d719a0f3680 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -1058,6 +1058,11 @@ m68k_expand_prologue (void) if (frame_pointer_needed) { +#ifdef TARGET_AMIGA + if (HAVE_ALTERNATE_FRAME_SETUP_F (fsize_with_regs)) + ALTERNATE_FRAME_SETUP_F (fsize_with_regs); + else +#endif if (fsize_with_regs == 0 && TUNE_68040) { /* On the 68040, two separate moves are faster than link.w 0. */ @@ -1067,6 +1072,10 @@ m68k_expand_prologue (void) m68k_set_frame_related (emit_move_insn (frame_pointer_rtx, stack_pointer_rtx)); } +#ifdef TARGET_AMIGA + else if (HAVE_ALTERNATE_FRAME_SETUP (fsize_with_regs)) + ALTERNATE_FRAME_SETUP (fsize_with_regs); +#endif else if (fsize_with_regs < 0x8000 || TARGET_68020) m68k_set_frame_related (emit_insn (gen_link (frame_pointer_rtx, @@ -1168,6 +1177,10 @@ m68k_expand_prologue (void) if (!TARGET_SEP_DATA && crtl->uses_pic_offset_table && flag_pic < 3) emit_insn (gen_load_got (pic_offset_table_rtx)); + +#ifdef TARGET_AMIGA + amigaos_restore_a4 (); +#endif } /* Return true if a simple (return) instruction is sufficient for this @@ -2163,6 +2176,8 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p) /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */ if (amiga_is_const_pic_ref(x)) return true; + if (!amigaos_legitimate_src(x)) + return false; #endif return m68k_decompose_address (mode, x, strict_p, &address); @@ -2185,7 +2200,11 @@ m68k_legitimate_mem_p (rtx x, struct m68k_address *address) bool m68k_legitimate_constant_p (machine_mode mode, rtx x) { - return mode != XFmode && !m68k_illegitimate_symbolic_constant_p (x); + return mode != XFmode && !m68k_illegitimate_symbolic_constant_p (x) +#ifdef TARGET_AMIGA + && amigaos_legitimate_src (x) +#endif + ; } /* Return true if X matches the 'Q' constraint. It must be a memory From 06f886edaaf71078005b5a79e727c279eb3249ab Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Nov 2017 23:16:19 +0100 Subject: [PATCH 254/303] fix opt_autoinc: handle nested neg/not correctly --- gcc/bbb-opts.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 2d3280230207..b6f630bd6522 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -850,8 +850,14 @@ insn_info::make_post_inc (int regno) if (is_compare ()) set = SET_SRC(set); rtx mem = get_dst_mem_regno () == regno ? SET_DEST(set) : SET_SRC(set); + if (src_op && get_src_mem_regno () == regno) - mem = XEXP(mem, 1); + { + if (src_op == NEG || src_op == NOT) + mem = XEXP(mem, 0); + else + mem = XEXP(mem, 1); + } rtx reg = XEXP(mem, 0); From 6095eeeb8f75626e72e6e3f023b4bb2dfebf7b6e Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 25 Nov 2017 23:17:43 +0100 Subject: [PATCH 255/303] refs #3: correct fix for peephole optimizer --- gcc/config/m68k/m68k.md | 4 +++- gcc/recog.c | 13 ------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 906fde496031..7b6f69835d10 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -7204,6 +7204,7 @@ "operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);") ;; Changing pea X.w into a move.l is no real win here. +;; SBF: also disable converting pea for baserel insns! (define_peephole2 [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 0 "const_int_operand" ""))) @@ -7213,7 +7214,8 @@ && !reg_mentioned_p (stack_pointer_rtx, operands[2]) && !(CONST_INT_P (operands[2]) && INTVAL (operands[2]) != 0 && IN_RANGE (INTVAL (operands[2]), -0x8000, 0x7fff) - && !valid_mov3q_const (INTVAL (operands[2])))" + && !valid_mov3q_const (INTVAL (operands[2]))) + && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(operands[2])" [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 0))) (set (match_dup 1) (match_dup 2))] { diff --git a/gcc/recog.c b/gcc/recog.c index de2340518e52..73d1fd1b1336 100644 --- gcc/recog.c +++ gcc/recog.c @@ -3249,19 +3249,6 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt) rtx_insn *new_insn; bool was_call = false; -#ifdef TARGET_AMIGA - /* SBF: splitting may yield invalid insns -> avoid it for the special pea insn! */ - for (int i = 0; i <= match_len; ++i) - { - rtx_insn * insn0 = peep2_insn_data[i].insn; - if (!PATTERN(insn0)) - continue; - rtx set0 = single_set(insn0); - if (set0 && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set0)) && MEM_P(SET_DEST(set0))) - return 0; - } -#endif - /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to match more than one insn, or to be split into more than one insn. */ old_insn = peep2_insn_data[peep2_current].insn; From edcaad7b5a906f1319f99f18f36cd0a9b20ef872 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 25 Nov 2017 23:31:57 +0100 Subject: [PATCH 256/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a3ce57172f94..4b4b584889d8 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171123-203556 +20171125-233156 From ea33fc6832c62dfda09e972a526ef2842a3efe85 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 26 Nov 2017 10:48:15 +0100 Subject: [PATCH 257/303] fix insn scan if src auto_inc is present, destination mem reg was always regarded as modified --- gcc/bbb-opts.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index b6f630bd6522..ee4e91a99b48 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1059,7 +1059,13 @@ insn_info::scan_rtx (rtx x) use = u; myuse = mu; } + + // avoid side effects from myuse -> def, e.g. adding the dst reg to def by src auto inc + mu = myuse; + myuse = 0; scan_rtx (SET_SRC(x)); + myuse |= mu; + int code = GET_CODE(SET_SRC(x)); if (code == ASM_OPERANDS) hard |= def | use; @@ -4181,7 +4187,7 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) if (!ii.make_post_inc (regno)) return 0; - log ("(i) auto_inc for %s at %d\n", reg_names[regno], index); + log ("(i) auto_inc for %s at %d - %d fixups\n", reg_names[regno], index, fixups.size()); // fix all offsets / adds for (std::set::iterator k = fixups.begin (); k != fixups.end (); ++k) From 73e0e6c763bd79928606dece20538b1a65a53683 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 26 Nov 2017 11:25:01 +0100 Subject: [PATCH 258/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4b4b584889d8..1c49eda6e46b 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171125-233156 +20171126-112501 From 28fa4c97279c23894bbabe479ec7f0675e1ac1c2 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 26 Nov 2017 12:26:06 +0100 Subject: [PATCH 259/303] fix const_cmp_sub --- gcc/bbb-opts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ee4e91a99b48..277f130f1ef4 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2868,7 +2868,7 @@ opt_const_cmp_to_sub (void) if (GET_MODE_SIZE(i0.get_mode()) > 4) continue; - if (!i0.is_dst_reg () && (!i0.is_src_const () || i0.get_src_op () == PLUS)) + if (!i0.is_dst_reg () || !i0.is_src_const () || i0.get_src_op ()) continue; if (i0.get_dst_regno () != i1.get_src_regno ()) From d1a50a4116660763379610abfa3e150f1db1e874 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 26 Nov 2017 12:53:56 +0100 Subject: [PATCH 260/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1c49eda6e46b..1f73e7437484 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171126-112501 +20171126-125355 From 18c192e42fc39de08a4f6cb6f241679b28cd5efc Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 26 Nov 2017 16:01:03 +0100 Subject: [PATCH 261/303] improved attribute/option checking --- gcc/config/m68k/amigaos.c | 14 ++++++++++---- gcc/config/m68k/amigaos.h | 6 ++++++ gcc/config/m68k/amigaos.opt | 6 +++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 9d2fc73d35f3..82dfae890f9f 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -672,6 +672,15 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI } else if (is_attribute_p ("saveds", name)) { + if (flag_pic < 3) + { + warning (OPT_Wattributes, "`%s' attribute is only usable with fbaserel", IDENTIFIER_POINTER(name)); + } + else + if (flag_resident) + { + error ("`saveds' can't be used with resident!\n"); + } } } else @@ -762,10 +771,7 @@ read_only_operand (rtx operand) rtx amigaos_struct_value_rtx (tree fntype, int incoming ATTRIBUTE_UNUSED) { -// if (fntype && aggregate_value_p (TREE_TYPE(fntype), fntype)) return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM); - -// return 0; } rtx @@ -887,7 +893,7 @@ void amigaos_add_offset_to_symbol(rtx * src) void amigaos_restore_a4 (void) { - if (flag_pic >= 3) + if (flag_pic >= 3 && !flag_resident) { tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); tree attr = lookup_attribute ("saveds", attrs); diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index fe300515fa5f..9f166d6f57c2 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -427,6 +427,12 @@ extern tree amigaos_handle_type_attribute(tree *, tree, tree, int, bool*); #define SUBTARGET_OVERRIDE_OPTIONS \ do \ { \ + if (flag_resident) \ + { \ + if (flag_pic) \ + error ("-fbaserel and -resident are mutual exclusiv\n"); \ + flag_pic = flag_resident; \ + } \ if (!TARGET_68020 && flag_pic==4) \ error ("-fbaserel32 is not supported on the 68000 or 68010\n"); \ if (amigaos_regparm > 0 && amigaos_regparm > AMIGAOS_MAX_REGPARM) \ diff --git a/gcc/config/m68k/amigaos.opt b/gcc/config/m68k/amigaos.opt index d87f884f06b3..07406d27a777 100644 --- gcc/config/m68k/amigaos.opt +++ gcc/config/m68k/amigaos.opt @@ -32,11 +32,11 @@ Target Report Var(flag_pic,4) data is addressed relative to a4 with 32 bit offsets resident -Target Common Report Var(flag_pic,3) +Target Common Report Var(flag_resident,3) data is addressed relative to a4, linked as resident resident32 -Target Common Report Var(flag_pic,4) +Target Common Report Var(flag_resident,4) data is addressed relative to a4 with 32 bit offsets, linked as resident mcrt= @@ -60,4 +60,4 @@ s a strcpy optimization v be verbose V be very verbose x dump insns -Default: -fbbb=+ +Default: -fbbb=+ which yields -fbbb=abcefimprs From c14a11d08caac02a69c6a7eb76e867586113aad7 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 26 Nov 2017 16:28:46 +0100 Subject: [PATCH 262/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1f73e7437484..216c38355e67 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171126-125355 +20171126-162846 From 9809cd847fa66de483a6994bb8ae37e1a014abea Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 27 Nov 2017 12:33:29 +0100 Subject: [PATCH 263/303] refs #4 - use correct name: ___a4_init --- gcc/config/m68k/amigaos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 82dfae890f9f..de2e2999eb60 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -899,7 +899,7 @@ amigaos_restore_a4 (void) tree attr = lookup_attribute ("saveds", attrs); if (attr || TARGET_RESTORE_A4 || TARGET_ALWAYS_RESTORE_A4) { - rtx a4 = gen_rtx_ASM_INPUT_loc(VOIDmode, "\tlea ___init_a4,a4", DECL_SOURCE_LOCATION (current_function_decl)); + rtx a4 = gen_rtx_ASM_INPUT_loc(VOIDmode, "\tlea ___a4_init,a4", DECL_SOURCE_LOCATION (current_function_decl)); a4->volatil = 1; emit_insn(a4); } From 486fefde971da0f1a5fb28f791b940ab7801912b Mon Sep 17 00:00:00 2001 From: fautomat Date: Mon, 27 Nov 2017 12:59:17 +0100 Subject: [PATCH 264/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 216c38355e67..ce0da3dfd125 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171126-162846 +20171127-125916 From 9147ce3cfcd7cf9a6eaa3e5793ae43fc7791c9ed Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 29 Nov 2017 19:26:05 +0100 Subject: [PATCH 265/303] fix opt_cmp_sub, prepare support for chip attribute, changes to baserel handling --- gcc/bbb-opts.c | 54 +++++++++------------------ gcc/config/m68k/amigaos-protos.h | 2 - gcc/config/m68k/amigaos.c | 80 +++++++++++++++++++++++++++------------- gcc/config/m68k/amigaos.h | 7 ++++ gcc/config/m68k/m68k.c | 13 ++++++- gcc/passes.c | 7 +++- 6 files changed, 96 insertions(+), 67 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 277f130f1ef4..4525f77acc2a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -177,7 +177,7 @@ class track_var /* only keep common values in both sides. */ void - merge (track_var * o, unsigned at) + merge (track_var * o, unsigned ) { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { @@ -2732,44 +2732,29 @@ opt_commute_add_move (void) for (unsigned index = 0; index + 1 < infos.size (); ++index) { - rtx_insn * insn = infos[index].get_insn (); - rtx set = single_set (insn); - if (!set) - continue; - - rtx reg1dst = SET_DEST(set); - if (!REG_P(reg1dst)) + insn_info & ii = infos[index]; + if (ii.get_dst_regno() < 8 || ii.get_dst_regno() > 15 || ii.get_src_op() != PLUS || ii.get_src_regno() == ii.get_dst_regno() || !ii.get_src_intval()) continue; - rtx plus = SET_SRC(set); - if (GET_CODE(plus) != PLUS) - continue; + insn_info & jj = infos[index + 1]; - rtx reg1src = XEXP(plus, 0); - if (!REG_P(reg1src) || reg1src == reg1dst) + if (!jj.get_dst_mem_reg() || jj.get_dst_mem_regno() != ii.get_src_regno() + || jj.get_src_regno() == ii.get_dst_regno() + || GET_MODE_SIZE(jj.get_mode()) != ii.get_src_intval()) continue; - rtx cnst = XEXP(plus, 1); - if (!CONST_INT_P(cnst)) - continue; + rtx_insn * insn = ii.get_insn (); - rtx_insn * next = infos[index + 1].get_insn (); + rtx_insn * next = jj.get_insn (); rtx set2 = single_set (next); - if (!set2) - continue; - rtx dst = SET_DEST(set2); - if (!MEM_P(dst) || GET_MODE_SIZE(GET_MODE(dst)) != INTVAL(cnst)) - continue; - - rtx memreg = XEXP(dst, 0); - if (!REG_P(memreg) || REGNO(memreg) != REGNO(reg1src)) + if (!MEM_P(dst)) continue; - rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), reg1dst); + rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), ii.get_dst_reg()); rtx newmem = replace_equiv_address_nv (dst, pinc); - rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(reg1dst, reg1src)); + rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(ii.get_dst_reg(), ii.get_src_reg())); if (!insn_invalid_p (newinsn, 1) && validate_change (next, &SET_DEST(set2), newmem, 1) && apply_change_group ()) { @@ -2779,7 +2764,7 @@ opt_commute_add_move (void) insn = emit_insn_before (newinsn, next); - add_reg_note (next, REG_INC, reg1dst); + add_reg_note (next, REG_INC, ii.get_dst_reg()); ++change_count; } @@ -4470,12 +4455,7 @@ namespace bool ispicref = false; // fix add PLUS/MINUS into the unspec offset if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS) - { - if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0))) - { - amigaos_add_offset_to_symbol(src); - } - } + ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0)); else ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(*src); @@ -4489,10 +4469,12 @@ namespace rtx reg = gen_reg_rtx (Pmode); rtx pat0 = gen_rtx_SET(reg, *src); - rtx_insn * n0 = emit_insn_before(pat0, insn); + //rtx_insn * n0 = + emit_insn_before(pat0, insn); rtx pat1 = gen_rtx_SET(dest, reg); - rtx_insn * n1 = emit_insn_before(pat1, insn); + //rtx_insn * n1 = + emit_insn_before(pat1, insn); SET_INSN_DELETED(insn); } diff --git a/gcc/config/m68k/amigaos-protos.h b/gcc/config/m68k/amigaos-protos.h index ce20a17d1840..e5cd6e950b52 100644 --- gcc/config/m68k/amigaos-protos.h +++ gcc/config/m68k/amigaos-protos.h @@ -53,5 +53,3 @@ extern struct rtx_def *amigaos_function_arg (CUMULATIVE_ARGS *, enum machine_mod extern tree amigaos_handle_decl_attribute (tree *, tree, tree, int, bool *); extern tree amigaos_handle_type_attribute (tree *, tree, tree, int, bool *); #endif - -extern void amigaos_add_offset_to_symbol(rtx *); diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index de2e2999eb60..ba8a5d757d21 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -682,10 +682,21 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI error ("`saveds' can't be used with resident!\n"); } } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to data", IDENTIFIER_POINTER(name)); + } } else { - warning (OPT_Wattributes, "`%s' attribute only applies to functions", IDENTIFIER_POINTER(name)); + if (is_attribute_p ("chip", name)) + { + // OK + } + else + { + warning (OPT_Wattributes, "`%s' attribute only applies to functions", IDENTIFIER_POINTER(name)); + } } return NULL_TREE ; } @@ -695,6 +706,46 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI return NULL_TREE ; } +#define AMIGA_CHIP_SECTION_NAME ".datachip" + +void +amiga_insert_attribute (tree decl, tree * attr) +{ + if (!*attr) + return; + + tree name = TREE_PURPOSE(*attr); + + if (is_attribute_p("chip", name)) + { + if (!TREE_TYPE(decl) == VAR_DECL) + { + error ("`chip' attribute can only be specified for variables"); + return; + } + + if (! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)) + { + error ("`chip' attribute cannot be specified for local variables"); + return; + } + /* The decl may have already been given a section attribute from + a previous declaration. Ensure they match. */ + if (DECL_SECTION_NAME (decl) == NULL) + warning (OPT_Wattributes, "`%s' attribute is not yet supported", IDENTIFIER_POINTER(name)); +// set_decl_section_name(decl, AMIGA_CHIP_SECTION_NAME); + else if (strcmp (DECL_SECTION_NAME (decl), AMIGA_CHIP_SECTION_NAME) ) + { + error_at (DECL_SOURCE_LOCATION(decl), + "`chip' attribute conflicts with previous declaration"); + } + } + else + { +// warning (OPT_Wattributes, "`%s' attribute unknown", IDENTIFIER_POINTER(name)); + } +} + extern bool m68k_rtx_costs (rtx, machine_mode, int, int, int *, bool); @@ -832,11 +883,10 @@ amigaos_legitimate_src (rtx src) if (GET_CODE(src) == PLUS || GET_CODE(src) == MINUS) { rtx x = XEXP(src, 0); + + /** handled in print_operand_address(...) */ if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x)) - { - amigaos_add_offset_to_symbol(&src); return true; - } return amigaos_legitimate_src(x) && amigaos_legitimate_src(XEXP(src, 1)); } @@ -868,28 +918,6 @@ amigaos_legitimate_src (rtx src) return true; } -void amigaos_add_offset_to_symbol(rtx * src) -{ - static char num[16]; - bool isplus = GET_CODE(*src) == PLUS; - rtx offset = XEXP(*src, 1); - sprintf(num, "%d", (int)INTVAL(offset)); - - /* unlink PLUS/MINUS */ - *src = XEXP(*src, 0); - - rtx plus = XEXP(*src, 0); - rtx cnst = XEXP(plus, 1); - rtx unspec = XEXP(cnst, 0); - rtx sym = XVECEXP(unspec, 0, 0); - const char * s = XSTR(sym, 0); - - /* create a new symbol containing the offset. */ - const char * t = concat(s, isplus ? "+" : "-", num, NULL); - XVECEXP(unspec, 0, 0) = gen_rtx_SYMBOL_REF(Pmode, t); -} - - void amigaos_restore_a4 (void) { diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 9f166d6f57c2..723c36969ad1 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -444,6 +444,7 @@ while (0) affects_type_identity } */ #define SUBTARGET_ATTRIBUTES \ { "asmregs", 0, 0, false, false, false, 0, true }, \ + { "chip", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute, false }, \ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\ true }, \ @@ -492,3 +493,9 @@ amigaos_alternate_frame_setup (int fsize); #define ALTERNATE_FRAME_SETUP(FSIZE) \ (amigaos_alternate_frame_setup ((FSIZE))) + +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES amiga_insert_attribute + +void +amiga_insert_attribute (tree decl, tree * attr); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 4d719a0f3680..f5daa0cbcc26 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -4835,6 +4835,14 @@ print_operand_address (FILE *file, rtx addr) print_operand_address(file, XEXP(addr, 0)); return; } + if (GET_CODE(addr) == PLUS && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(addr, 0))) + { + fprintf (file, "%d+", (int) INTVAL (XEXP(addr, 1))); + print_operand_address(file, XEXP(XEXP(addr, 0),0)); + return; + } + + if (symbolic_operand(addr, VOIDmode)) { memset (&address, 0, sizeof (address)); @@ -4843,7 +4851,10 @@ print_operand_address (FILE *file, rtx addr) else #endif if (!m68k_decompose_address (QImode, addr, true, &address)) - gcc_unreachable (); + { + debug_rtx(addr); + gcc_unreachable (); + } if (address.code == PRE_DEC) fprintf (file, MOTOROLA ? "-(%s)" : "%s@-", diff --git a/gcc/passes.c b/gcc/passes.c index 407160f4e4d6..b216ee028245 100644 --- gcc/passes.c +++ gcc/passes.c @@ -2276,7 +2276,8 @@ void dump_insns(char const * name) for (insn = get_insns(); insn; insn = next) { next = NEXT_INSN(insn); -#if 1 + debug_rtx(insn); +#if 0 if (NONJUMP_INSN_P (insn)) { rtx set= single_set (insn); @@ -2290,6 +2291,7 @@ void dump_insns(char const * name) } } + /* Execute PASS. */ bool @@ -2299,7 +2301,8 @@ execute_one_pass (opt_pass *pass) bool gate_status; -// dump_insns(pass->name); + if (string_bbb_opts && strchr (string_bbb_opts, 'Y')) + dump_insns(pass->name); /* IPA passes are executed on whole program, so cfun should be NULL. Other passes need function context set. */ From 4a14629a3a38f9c4d043813eb36247a5a0b3adc7 Mon Sep 17 00:00:00 2001 From: fautomat Date: Wed, 29 Nov 2017 19:55:45 +0100 Subject: [PATCH 266/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ce0da3dfd125..4aee726e0fe2 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171127-125916 +20171129-195545 From e2608938b1210496cf528a280030a5906a6991e5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 1 Dec 2017 20:06:38 +0100 Subject: [PATCH 267/303] fix opt_auto_inc again --- gcc/bbb-opts.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 4525f77acc2a..7c8fc94ed8a6 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -177,7 +177,7 @@ class track_var /* only keep common values in both sides. */ void - merge (track_var * o, unsigned ) + merge (track_var * o, unsigned) { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { @@ -928,7 +928,7 @@ insn_info::auto_inc_fixup (int regno, int size) SET_SRC(set) = XEXP(src, 0); } else - XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size); + XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size); } else if (get_src_mem_regno () == regno) { @@ -2733,14 +2733,14 @@ opt_commute_add_move (void) for (unsigned index = 0; index + 1 < infos.size (); ++index) { insn_info & ii = infos[index]; - if (ii.get_dst_regno() < 8 || ii.get_dst_regno() > 15 || ii.get_src_op() != PLUS || ii.get_src_regno() == ii.get_dst_regno() || !ii.get_src_intval()) + if (ii.get_dst_regno () < 8 || ii.get_dst_regno () > 15 || ii.get_src_op () != PLUS + || ii.get_src_regno () == ii.get_dst_regno () || !ii.get_src_intval ()) continue; insn_info & jj = infos[index + 1]; - if (!jj.get_dst_mem_reg() || jj.get_dst_mem_regno() != ii.get_src_regno() - || jj.get_src_regno() == ii.get_dst_regno() - || GET_MODE_SIZE(jj.get_mode()) != ii.get_src_intval()) + if (!jj.get_dst_mem_reg () || jj.get_dst_mem_regno () != ii.get_src_regno () + || jj.get_src_regno () == ii.get_dst_regno () || GET_MODE_SIZE(jj.get_mode()) != ii.get_src_intval ()) continue; rtx_insn * insn = ii.get_insn (); @@ -2751,10 +2751,10 @@ opt_commute_add_move (void) if (!MEM_P(dst)) continue; - rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), ii.get_dst_reg()); + rtx pinc = gen_rtx_POST_INC(GET_MODE(dst), ii.get_dst_reg ()); rtx newmem = replace_equiv_address_nv (dst, pinc); - rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(ii.get_dst_reg(), ii.get_src_reg())); + rtx_insn * newinsn = make_insn_raw (gen_rtx_SET(ii.get_dst_reg (), ii.get_src_reg ())); if (!insn_invalid_p (newinsn, 1) && validate_change (next, &SET_DEST(set2), newmem, 1) && apply_change_group ()) { @@ -2764,7 +2764,7 @@ opt_commute_add_move (void) insn = emit_insn_before (newinsn, next); - add_reg_note (next, REG_INC, ii.get_dst_reg()); + add_reg_note (next, REG_INC, ii.get_dst_reg ()); ++change_count; } @@ -4136,6 +4136,9 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) bool fix = false; if (jj.get_src_mem_regno () == regno) { + if (jj.get_dst_regno () == regno) + return 0; + if (jj.get_src_mem_addr () < size) return 0; @@ -4146,6 +4149,9 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) } if (jj.get_dst_mem_regno () == regno) { + if (jj.get_src_regno () == regno) + return 0; + if (jj.get_dst_mem_addr () < size) return 0; @@ -4172,7 +4178,7 @@ try_auto_inc (unsigned index, insn_info & ii, rtx reg) if (!ii.make_post_inc (regno)) return 0; - log ("(i) auto_inc for %s at %d - %d fixups\n", reg_names[regno], index, fixups.size()); + log ("(i) auto_inc for %s at %d - %d fixups\n", reg_names[regno], index, fixups.size ()); // fix all offsets / adds for (std::set::iterator k = fixups.begin (); k != fixups.end (); ++k) @@ -4220,13 +4226,12 @@ opt_autoinc () // if ((ii.get_myuse () & 0xff0000)) // continue; - rtx reg = 0; if (ii.is_src_mem () && ii.get_src_mem_regno () >= 8 && !ii.get_src_mem_addr () && !ii.get_src_autoinc () && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_mem_regno () != ii.get_dst_regno ()) change_count += try_auto_inc (index, ii, ii.get_src_mem_reg ()); - if (!reg && ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () - && ii.get_src_mem_regno () != ii.get_dst_mem_regno ()) + if (ii.is_dst_mem () && ii.get_dst_mem_regno () >= 8 && !ii.get_dst_intval () && !ii.get_dst_autoinc () + && ii.get_src_mem_regno () != ii.get_dst_mem_regno () && ii.get_src_regno () != ii.get_dst_mem_regno ()) change_count += try_auto_inc (index, ii, ii.get_dst_mem_reg ()); } @@ -4462,19 +4467,18 @@ namespace if (ispicref) { rtx dest = SET_DEST(set); - if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC - ) + if (MEM_P(dest) && GET_CODE(XEXP(dest, 0)) != PRE_DEC) { // split the insn rtx reg = gen_reg_rtx (Pmode); rtx pat0 = gen_rtx_SET(reg, *src); //rtx_insn * n0 = - emit_insn_before(pat0, insn); + emit_insn_before (pat0, insn); rtx pat1 = gen_rtx_SET(dest, reg); //rtx_insn * n1 = - emit_insn_before(pat1, insn); + emit_insn_before (pat1, insn); SET_INSN_DELETED(insn); } From 34ff5f41808c0f6eef3ea36cb6592f696b568e0f Mon Sep 17 00:00:00 2001 From: fautomat Date: Fri, 1 Dec 2017 20:33:49 +0100 Subject: [PATCH 268/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4aee726e0fe2..5ca5b245f261 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171129-195545 +20171201-203349 From 865d8c2a52ee44716669dc3353d5cd10f2cc2836 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 3 Dec 2017 23:15:02 +0100 Subject: [PATCH 269/303] fix opt_auto_inc if set is 0 --- gcc/bbb-opts.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 7c8fc94ed8a6..757cc93dda94 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -845,6 +845,9 @@ insn_info::make_post_inc (int regno) // convert into POST_INC rtx set0 = single_set (new_insn); + if (!set0) + return false; + rtx set = set0; if (is_compare ()) From d565753800ac3d71d6367a3c5f7db440b2068e48 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sun, 3 Dec 2017 23:43:43 +0100 Subject: [PATCH 270/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5ca5b245f261..e90d802ff727 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171201-203349 +20171203-234342 From 7018006ca506699e3241293713bca07d71bea88c Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 10 Dec 2017 16:00:32 +0100 Subject: [PATCH 271/303] more baserel fixes + cleanup= less changes to original code --- gcc/bbb-opts.c | 395 +++++++++++++++++++++++++++++------------ gcc/config/m68k/amigaos.c | 76 ++++++-- gcc/config/m68k/constraints.md | 8 +- gcc/config/m68k/m68k.c | 35 +++- gcc/config/m68k/m68k.md | 16 +- gcc/config/m68k/m68kamigaos.h | 19 +- gcc/final.c | 6 + gcc/passes.c | 2 +- 8 files changed, 390 insertions(+), 167 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 757cc93dda94..dca287181b3a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -70,12 +70,20 @@ #include "tree-pass.h" #include "conditions.h" #include "langhooks.h" +#include +#include +#include int be_very_verbose; bool be_verbose; extern struct lang_hooks lang_hooks; +static void +update_insn_infos (void); +static unsigned +track_regs (); + /* Lookup of the current function name. */ extern tree current_function_decl; static tree last_function_decl; @@ -116,63 +124,210 @@ enum proepis IN_CODE, IN_PROLOGUE, IN_EPILOGUE, IN_EPILOGUE_PARALLEL_POP }; +/** + * What's needed to track values? + */ class track_var { - unsigned * indexes; - rtx * values; - unsigned * versions; + rtx value[FIRST_PSEUDO_REGISTER]; + unsigned mask[FIRST_PSEUDO_REGISTER]; + + bool + extend (rtx * z, unsigned * mask, machine_mode dstMode, rtx x) + { + switch (GET_CODE(x)) + { + case CONST_INT: + case CONST_FIXED: + case CONST_DOUBLE: + case SYMBOL_REF: + case LABEL_REF: + /* these can be used directly. */ + *z = x; + return true; + + case REG: + { + rtx v = value[REGNO(x)]; + /* try to expand the register. */ + if (v) + { + if (GET_MODE(v) != VOIDmode && dstMode != GET_MODE(v)) + return false; + + *mask |= mask[REGNO(x)]; + *z = value[REGNO(x)]; + return true; + } + + /* store the reg otherwise. */ + *mask |= (1 << REGNO(x)); + *z = x; + return true; + } + case PLUS: + case MINUS: + // handle only in combination with const + { + rtx y = XEXP(x, 0); + if (GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref(y)) + return false; + + if (GET_CODE(x) == PLUS) // create an own plus to be able to modify the constant offset (later). + *z = gen_rtx_PLUS(GET_MODE(x), y, XEXP(x, 1)); + else + *z = gen_rtx_MINUS(GET_MODE(x), y, XEXP(x, 1)); + return true; + } + + /* memory reads. */ + case MEM: + { + rtx m = XEXP(x, 0); + switch (GET_CODE(m)) + { + case SYMBOL_REF: + case LABEL_REF: + /* these can be used directly. */ + *z = x; + return true; + + case REG: + if (!extend (&m, mask, dstMode, m)) + return false; + + *z = gen_rtx_MEM (GET_MODE(x), m); + return true; + + case PLUS: + case MINUS: + // handle only in combination with const + { + rtx y = XEXP(m, 0); + if (!REG_P( + y) && GET_CODE(y) != SYMBOL_REF && GET_CODE(y) == LABEL_REF && amiga_is_const_pic_ref(y)) + return false; + + if (REG_P(y)) + if (!extend (&y, mask, dstMode, y)) + return false; + + if (GET_CODE(x) == PLUS) // create an own plus to be able to modify the constant offset (later). + m = gen_rtx_PLUS(GET_MODE(m), y, XEXP(m, 1)); + else + m = gen_rtx_MINUS(GET_MODE(m), y, XEXP(m, 1)); + + *z = gen_rtx_MEM (GET_MODE(x), m); + return true; + } + } + return false; + } + + default: + return false; + } + } public: - track_var (track_var const * o = 0) : - indexes ((unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))), values ( - (rtx *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(rtx))), versions ( - (unsigned *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof(unsigned))) + track_var (track_var const * o = 0) { if (o) assign (o); + else + for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + value[i] = 0; + mask[i] = 0; + } + } + + rtx + get (unsigned regno) + { + if (regno >= FIRST_PSEUDO_REGISTER) + return 0; + + return value[regno]; } void - set (unsigned regno, unsigned index, rtx rtx, unsigned ver) + set (machine_mode mode, unsigned regno, rtx x, unsigned index) { if (regno >= FIRST_PSEUDO_REGISTER) return; - indexes[regno] = index; - values[regno] = rtx; - versions[regno] = ver; + if (!extend (&value[regno], &mask[regno], mode, x)) + { + clear (regno, index); + } } - unsigned - get_index (unsigned regno) const + bool + equals (unsigned regno, rtx x) { if (regno >= FIRST_PSEUDO_REGISTER) - return 0; - return indexes[regno]; + return false; + + if (x == 0 || value[regno] == 0) + return false; + + rtx z = 0; + unsigned m = 0; + if (!extend (&z, &m, GET_MODE(x), x)) + return false; + + return rtx_equal_p (z, value[regno]); } - rtx - get_value (unsigned regno) const + void + clear (unsigned regno, unsigned index) { if (regno >= FIRST_PSEUDO_REGISTER) - return 0; - return values[regno]; + return; + + value[regno] = gen_rtx_CONST_INT (VOIDmode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); + mask[regno] = FIRST_PSEUDO_REGISTER; } - unsigned - get_version (unsigned regno) const + void + clear_aftercall (unsigned index) { - if (regno >= FIRST_PSEUDO_REGISTER) - return 0; - return versions[regno]; + for (int i = 2; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (mask[i]) + { + value[i] = 0; + mask[i] = 0; + } + } + clear (0, index); + clear (1, index); + clear (8, index); + clear (9, index); } void - assign (track_var const * o) const + clear_for_mask (unsigned def, unsigned index) { - memcpy (indexes, o->indexes, FIRST_PSEUDO_REGISTER * sizeof(unsigned)); - memcpy (values, o->values, FIRST_PSEUDO_REGISTER * sizeof(rtx)); - memcpy (versions, o->versions, FIRST_PSEUDO_REGISTER * sizeof(unsigned)); + if (!def) + return; + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + { + // register changed or used somehow + if ((1 << regno) & def) + clear (regno, index); + } + } + + void + assign (track_var const * o) + { + for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + value[i] = o->value[i]; + mask[i] = o->mask[i]; + } } /* only keep common values in both sides. */ @@ -181,8 +336,11 @@ class track_var { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i])) - values[i] = o->values[i] = 0; + if (!rtx_equal_p (value[i], o->value[i])) + { + value[i] = o->value[i] = 0; + mask[i] = mask[i] = 0; + } } } @@ -192,9 +350,8 @@ class track_var { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - if (versions[i] != o->versions[0] || !rtx_equal_p (values[i], o->values[i])) - if (values[i]) - return false; + if (!rtx_equal_p (value[i], o->value[i])) + return false; } return true; } @@ -931,7 +1088,7 @@ insn_info::auto_inc_fixup (int regno, int size) SET_SRC(set) = XEXP(src, 0); } else - XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size); + XEXP(src, 1) = gen_rtx_CONST_INT (GET_MODE(XEXP(src, 1)), src_intval -= size); } else if (get_src_mem_regno () == regno) { @@ -1367,11 +1524,11 @@ update_insn2index () static void update_label2jump () { + update_insn2index (); + for (unsigned index = 0; index < infos.size (); ++index) { insn_info & ii = infos[index]; - insn2info.insert (std::make_pair (ii.get_insn (), &ii)); - if (ii.is_label ()) for (l2j_iterator i = label2jump.find (ii.get_insn ()->u2.insn_uid), k = i; i != label2jump.end () && i->first == k->first; ++i) @@ -1598,12 +1755,47 @@ is_reg_dead (unsigned regno, unsigned _pos) return true; } +bool dump_reg_track; +void +append_reg_cache (FILE * f, rtx_insn * insn) +{ + i2i_iterator i = insn2info.find (insn); + if (i == insn2info.end ()) + return; + + insn_info & jj = *i->second; + unsigned index = jj.get_index (); + if (index + 1 < infos.size ()) + ++index; + insn_info & ii = infos[index]; + + track_var * track = ii.get_track_var (); + if (track == 0) + return; + + fprintf (f, "\n"); + + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + { + rtx v = track->get (regno); + if (v == 0) + continue; + +// if (GET_CODE(v) == CONST_INT && GET_MODE(v) == VOIDmode) +// continue; + + fprintf (f, "%s=", reg_names[regno]); + + print_inline_rtx (f, v, 12); + fprintf (f, "\n"); + } +} + /* helper stuff to enhance the asm output. */ int my_flag_regusage; void append_reg_usage (FILE * f, rtx_insn * insn) { - i2i_iterator i = insn2info.find (insn); if (i == insn2info.end ()) return; @@ -3635,53 +3827,48 @@ opt_shrink_stack_frame (void) /* Update the insn_infos to 'know' the value for each register. * - * atm only assignments to registers are optimized. + * assignments to registers are optimized by knowing the value. If the same value is assigned, omit that insn. * - * We track register aliases: + * I'm tracking * - * ;10 - * move.l 4(a0),d0 + * rtx - the value * - * ;15 - * move.l d0,d1 + * mask - the referenced registers in the value, 0 means that rtx is const, with baserel a4 is not tracked * + * if there is a value for the referenced register(s), the value is extended * - * ;18 - * move.l d1,d2 + * e.g. * - * - results into d0 is an alias for d1 (and vice versa). - * - to identify if a register is still changed, we also track the line where it was assigned. - * - in addition to register aliases memory reads are tracked too for normal memory access (e.g. no auto inc) - * but not if the memory read is marked as volatile + * ; line 2 + * move.l 12(a7),a0 * - * E.g. + * -> rtx = mem(plus(a7, 12)); 0x8000 * - * d0[10]: 4(a0)[10] - * d1[15]: d0[10] - * d2[18]: d1[15] + * ; line 10 + * move.l 4(a0),d0 * - * with that information we know that d2[18] also contains 4(a0)[10] + * -> rtx = mem(plus(mem(plus(a7, 12)), 4)); 0x8000; extended with value from a0, thus a7 is used only * - * info to track per register: - * line index where the value was assigned - * rtx which was assigned - or null if not a usable rtx - * reg line index - if rtx is a register + * ;15 + * lea _label,a1 * - * for each assignment which is not to a register the rtx are scanned and set to null on match + * -> rtx = symbol_ref(_label) ; 0x0000 == const * * on jumps the current state is duplicated and merged at the given label * * on merge only identical info is kept, rest is discarded * - * for each insn first the track info for all defined regs is discarded before the new one is set. + * for each insn for all defined regs the value and mask is discarded before a new value is set. + * + * for each insn which is writing to memory, all non const values are discarded. * * - * after the track info is complete, each insn is evaluated agains the track info. + * after the track info is complete, each insn setting a register is evaluated against the track info. * * now redundant loads are found and eliminated - * also unused assignments are found an eliminated * */ + static unsigned track_regs () { @@ -3733,26 +3920,19 @@ track_regs () ii.get_track_var ()->assign (track); int dregno = ii.get_dst_regno (); + track->clear (dregno, index); + unsigned def = ii.get_def () & 0xffffff; - if (def) - { - for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) - { - // register changed or used somehow - if (((1 << regno) & def) - || (track->get_index (regno) && (infos[track->get_index (regno)].get_myuse () & def))) - track->set (regno, index, 0, index); - } - // clear on self update - if (def & ii.get_myuse ()) - track->set (dregno, index, 0, index); - } + track->clear_for_mask (def, index); if (ii.is_compare ()) continue; if (ii.is_call ()) - continue; + { + track->clear_aftercall (index); + continue; + } rtx set = single_set (ii.get_insn ()); @@ -3786,21 +3966,7 @@ track_regs () if (ii.is_src_mem () && src->volatil) continue; - // add the entry - determine the version - use 0 for const values - unsigned version; - if (GET_CODE(src) != CONST_INT && GET_CODE(src) != CONST_FIXED && GET_CODE(src) != CONST_DOUBLE) - { - if (ii.get_src_regno () >= 0) - version = track->get_index (ii.get_src_regno ()); - else if (ii.get_src_mem_regno () >= 0) - version = track->get_index (ii.get_src_mem_regno ()); - else - version = index; - } - else - version = 0; - - track->set (dregno, index, src, version); + track->set (ii.get_mode (), dregno, src, index); } delete track; } @@ -3843,35 +4009,23 @@ opt_elim_dead_assign (int blocked_regno) { track_var * track = ii.get_track_var (); -// if (ii.get_src_regno() == 8 && ii.get_dst_regno() == 7) -// printf("%d: move %d,%d: v=%d (%d->%d), i=%d (%d->%d)\n", index, ii.get_src_regno(), ii.get_dst_regno(), -// track->get_version(ii.get_src_regno()), infos[track->get_version(ii.get_src_regno())].get_src_regno(), infos[track->get_version(ii.get_src_regno())].get_dst_regno(), -// track->get_index(ii.get_dst_regno()), infos[track->get_index(ii.get_dst_regno())].get_src_regno(), infos[track->get_index(ii.get_dst_regno())].get_dst_regno()); - rtx src = SET_SRC(set); - if (rtx_equal_p (track->get_value (ii.get_dst_regno ()), src)) + if (track->equals (ii.get_dst_regno (), src)) { - if ((REG_P(src) && track->get_version (ii.get_dst_regno ()) == track->get_index (ii.get_src_regno ())) - || !REG_P(src)) - { - log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); - SET_INSN_DELETED(insn); - ++change_count; - continue; - } + log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; } - // check reverse assignment - if (REG_P(src)) + + if (ii.get_src_reg () && track->equals (ii.get_src_regno (), SET_DEST(set))) { - if (REG_P(src) && rtx_equal_p (track->get_value (ii.get_src_regno ()), SET_DEST(set)) - && track->get_version (ii.get_src_regno ()) == track->get_index (ii.get_dst_regno ())) - { - log ("(e) %d: eliminate redundant load to %s\n", index, reg_names[ii.get_dst_regno ()]); - SET_INSN_DELETED(insn); - ++change_count; - continue; - } + log ("(e) %d: eliminate redundant reverse load to %s\n", index, reg_names[ii.get_dst_regno ()]); + SET_INSN_DELETED(insn); + ++change_count; + continue; } + } } return change_count; @@ -4300,6 +4454,7 @@ namespace unsigned pass_bbb_optimizations::execute_bbb_optimizations (void) { + dump_reg_track = strchr (string_bbb_opts, 'R') != 0; be_very_verbose = strchr (string_bbb_opts, 'V') != 0; be_verbose = strchr (string_bbb_opts, 'v') != 0; if (be_verbose && be_very_verbose) @@ -4380,6 +4535,12 @@ namespace if (strchr (string_bbb_opts, 'X') || strchr (string_bbb_opts, 'x')) dump_insns ("bbb", strchr (string_bbb_opts, 'X')); + if (dump_reg_track) + { + update_insns (); + track_regs (); + } + return r; } @@ -4463,9 +4624,9 @@ namespace bool ispicref = false; // fix add PLUS/MINUS into the unspec offset if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS) - ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(*src, 0)); + ispicref = amiga_is_const_pic_ref(XEXP(*src, 0)); else - ispicref = CONST_PLUS_PIC_REG_CONST_UNSPEC_P(*src); + ispicref = amiga_is_const_pic_ref(*src); if (ispicref) { diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index ba8a5d757d21..298bcb18300c 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -793,17 +793,47 @@ amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_U /** * Does x reference the pic_reg and is const or plus? */ +static int +_amiga_is_const_pic_ref (const_rtx x) +{ + if (GET_CODE(x) == PLUS || GET_CODE(x) == MINUS) + { + if (GET_CODE(XEXP(x, 1)) == CONST_INT) + return _amiga_is_const_pic_ref(XEXP(x, 0)); + return false; + } + + if (GET_CODE(x) == CONST) + x = XEXP(x, 0); + if (GET_CODE(x) != PLUS) + return false; + + const_rtx reg = XEXP(x, 0); + if (!REG_P(reg) && REGNO(reg) != PIC_REG) + return false; + + const_rtx unspec = XEXP(x, 1); + while (GET_CODE(unspec) == PLUS || GET_CODE(unspec) == CONST) + unspec = XEXP(unspec, 0); + + if (GET_CODE(unspec) != UNSPEC) + return false; + + return true; +} + int -amiga_is_const_pic_ref (const_rtx x) +amiga_is_const_pic_ref (const_rtx cnst) { - const_rtx y = x; if (flag_pic < 3) - return false; - while (GET_CODE(y) == CONST || GET_CODE(y) == PLUS) - y = XEXP(y, 0); - return (x != y && REG_P(y) && REGNO(y) == PIC_REG); + return true; + int r = _amiga_is_const_pic_ref (cnst); +// fprintf(stderr, r ? "valid pic: " : "invalid pic: "); +// debug_rtx(cnst); + return r; } + /* Does operand (which is a symbolic_operand) live in text space? If so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. @@ -880,15 +910,27 @@ amigaos_legitimate_src (rtx src) if (flag_pic < 3) return true; + if (MEM_P(src)) + { + rtx x = XEXP(src, 0); + if (GET_CODE(x) == PLUS || GET_CODE(x) == MINUS) { + if (amiga_is_const_pic_ref(XEXP(x, 0)) + || amiga_is_const_pic_ref(XEXP(x, 1))) + return false; + } + return true; + } + if (GET_CODE(src) == PLUS || GET_CODE(src) == MINUS) { rtx x = XEXP(src, 0); + rtx y = XEXP(src, 1); /** handled in print_operand_address(...) */ - if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x)) - return true; + if (amiga_is_const_pic_ref(x)) + return GET_CODE(y) == CONST_INT; - return amigaos_legitimate_src(x) && amigaos_legitimate_src(XEXP(src, 1)); + return amigaos_legitimate_src(x) && amigaos_legitimate_src(y) && !amiga_is_const_pic_ref(y); } if (GET_CODE(src) == CONST) @@ -903,16 +945,12 @@ amigaos_legitimate_src (rtx src) if (!REG_P(reg)) return true; -// debug_rtx(src); return false; } } if (GET_CODE(op) == UNSPEC) - { -// debug_rtx(src); - return false; - } + return false; } return true; @@ -986,3 +1024,13 @@ amigaos_alternate_frame_setup (int fsize) #endif } +#if 0 +extern bool debug_recog(char const * txt, int which_alternative, int n, rtx * operands) +{ + fprintf(stderr, "%s: %d ", txt, which_alternative); + for (int i = 0; i < n; ++i) + print_rtl(stderr, operands[i]); + fprintf(stderr, "\n--\n"); + return true; +} +#endif diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md index 0d9b1b69ab18..1223852570c1 100644 --- gcc/config/m68k/constraints.md +++ gcc/config/m68k/constraints.md @@ -1,5 +1,5 @@ ;; Constraint definitions for m68k -;; Copyright (C) 2007-2016 Free Software Foundation, Inc. +;; Copyright (C) 2007-2015 Free Software Foundation, Inc. ;; This file is part of GCC. @@ -97,12 +97,6 @@ (match_test "!TARGET_PCREL") (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)"))) -(define_constraint "t" - "Used for operands that satisfy 's' without PIC stuff, when -mpcrel is not in effect." - (and (match_code "symbol_ref,label_ref,const") - (match_test "!TARGET_PCREL") - (match_test "!flag_pic || !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(op)"))) - (define_memory_constraint "Q" "Means address register indirect addressing mode." (and (match_code "mem") diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index f5daa0cbcc26..a655ed8476bb 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2176,8 +2176,10 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p) /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */ if (amiga_is_const_pic_ref(x)) return true; + if (!amigaos_legitimate_src(x)) return false; + #endif return m68k_decompose_address (mode, x, strict_p, &address); @@ -2530,7 +2532,7 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, /* SBF: Does the symbol use common or bss and qualifies for pic_reg? * Do not ref to .text via pic_reg! */ - if (!SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl))) + if (GET_CODE (orig) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl))) { /* SBF: unfortunately using the wrapped symbol without MEM does not work. * The pic_ref reference gets decomposed and leads to no working code. @@ -4603,7 +4605,7 @@ print_operand (FILE *file, rtx op, int letter) && INTVAL (XEXP (op, 0)) >= -0x8000) #ifdef TARGET_AMIGA /* SBF: Do not append some 'l' with baserel(32). */ - && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(op, 0)) + && !amiga_is_const_pic_ref(XEXP(op, 0)) #endif ) fprintf (file, MOTOROLA ? ".l" : ":l"); @@ -4830,12 +4832,35 @@ print_operand_address (FILE *file, rtx addr) /* * SBF: remove the const wrapper. */ - if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(addr)) + if (amiga_is_const_pic_ref(addr)) { - print_operand_address(file, XEXP(addr, 0)); + /* handle (plus (unspec ) (const_int) */ + rtx *x = &addr; + while (GET_CODE(*x) != PLUS) + x = &XEXP(*x, 0); + + x = &XEXP(*x, 1); // CONST + if (GET_CODE(*x) == CONST) + x = &XEXP(*x, 0); + + /* if there is a plus - swap it. + * we want n+symbol:W (not symbol:W+n) + */ + if (GET_CODE(*x) == PLUS) + { + rtx plus = *x; + fprintf (file, "%d+", (int) INTVAL (XEXP(plus, 1))); + + *x = XEXP(plus, 0); + print_operand_address(file, XEXP(addr, 0)); + *x = plus; + } + else + print_operand_address(file, XEXP(addr, 0)); + return; } - if (GET_CODE(addr) == PLUS && CONST_PLUS_PIC_REG_CONST_UNSPEC_P(XEXP(addr, 0))) + if (GET_CODE(addr) == PLUS && amiga_is_const_pic_ref(XEXP(addr, 0))) { fprintf (file, "%d+", (int) INTVAL (XEXP(addr, 1))); print_operand_address(file, XEXP(XEXP(addr, 0),0)); diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 7b6f69835d10..05ef02027f01 100644 --- gcc/config/m68k/m68k.md +++ gcc/config/m68k/m68k.md @@ -500,7 +500,7 @@ [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>") (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))] - "!TARGET_COLDFIRE && (flag_pic < 3 || GET_CODE(operands[1]) != CONST || GET_CODE(XEXP(operands[1], 0)) != PLUS || !REG_P(XEXP(XEXP(operands[1], 0), 0)) || REGNO(XEXP(XEXP(operands[1], 0), 0)) != PIC_REG)" + "!TARGET_COLDFIRE" { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.l %1,%0"; @@ -955,8 +955,8 @@ (define_insn "*movsi_m68k" ;; Notes: make sure no alternative allows g vs g. ;; We don't allow f-regs since fixed point cannot go in them. - [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<") - (match_operand:SI 1 "general_src_operand" "damSnt,T,n,i"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<") + (match_operand:SI 1 "general_src_operand" "damSnT,n,i"))] "!TARGET_COLDFIRE && reload_completed" { return output_move_simode (operands); @@ -966,8 +966,8 @@ ;; force integer constants in range for a moveq to be reloaded ;; if they are headed for memory. (define_insn "*movsi_m68k2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=g,a,d,a<") - (match_operand:SI 1 "general_src_operand" "damSKt,T,n,i"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<") + (match_operand:SI 1 "general_src_operand" "damSKT,n,i"))] "!TARGET_COLDFIRE" { @@ -2468,7 +2468,7 @@ (define_insn "*addsi3_internal" [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,d,a") (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0") - (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLt,mSrIKLt")))] + (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))] "! TARGET_COLDFIRE" @@ -7090,8 +7090,6 @@ operands[1] = gen_rtx_REG (Pmode, PIC_REG); return MOTOROLA ? "move.l %?(%1),%0" : "movel %1@(%?), %0"; } - else if (TARGET_AMIGAOS) - return "lea (%%pc, __GLOBAL_OFFSET_TABLE_), %0"; else if (MOTOROLA) { if (TARGET_COLDFIRE) @@ -7215,7 +7213,7 @@ && !(CONST_INT_P (operands[2]) && INTVAL (operands[2]) != 0 && IN_RANGE (INTVAL (operands[2]), -0x8000, 0x7fff) && !valid_mov3q_const (INTVAL (operands[2]))) - && !CONST_PLUS_PIC_REG_CONST_UNSPEC_P(operands[2])" + && !amiga_is_const_pic_ref(operands[2])" [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 0))) (set (match_dup 1) (match_dup 2))] { diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 0e982c12da9c..43ffcd0add39 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -700,18 +700,17 @@ extern int amiga_is_const_pic_ref(const_rtx x); ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ || GET_CODE (X) == HIGH \ - ) && !amiga_is_const_pic_ref(X)) + )) + /* Given that symbolic_operand(X), return TRUE if no special base relative relocation is necessary */ -#define LEGITIMATE_BASEREL_OPERAND_P(X) \ - (flag_pic >= 3 && read_only_operand (X)) - #undef LEGITIMATE_PIC_OPERAND_P #define LEGITIMATE_PIC_OPERAND_P(X) ( \ - ! symbolic_operand (X, VOIDmode) || LEGITIMATE_BASEREL_OPERAND_P (X)) + ! symbolic_operand (X, VOIDmode) && \ + ! amiga_is_const_pic_ref(X)) // (GET_CODE(X) == CONST && (GET_CODE(XEXP(X, 0)) == SYMBOL_REF || GET_CODE(XEXP(X, 0)) == LABEL_REF) && !CONSTANT_POOL_ADDRESS_P (XEXP(X, 0))) || @@ -742,12 +741,4 @@ extern int amiga_is_const_pic_ref(const_rtx x); extern int amigaos_function_arg_reg(unsigned regno); -/* SBF: macro to test for const via pic_reg. */ -#define CONST_PLUS_PIC_REG_CONST_UNSPEC_P(x) \ - (GET_CODE(x) == CONST \ - && GET_CODE(XEXP(x, 0)) == PLUS \ - && REG_P(XEXP(XEXP(x, 0), 0)) \ - && REGNO(XEXP(XEXP(x, 0), 0)) == PIC_REG \ - && GET_CODE(XEXP(XEXP(x, 0), 1)) == CONST \ - && GET_CODE(XEXP(XEXP(XEXP(x, 0), 1), 0)) == UNSPEC \ - ) +//extern bool debug_recog(char const * txt, int which_alternative, int n, rtx * operands); diff --git a/gcc/final.c b/gcc/final.c index 009d8eca6baf..fa8b2964a40d 100644 --- gcc/final.c +++ gcc/final.c @@ -3626,6 +3626,10 @@ output_asm_insn (const char *templ, rtx *operands) { extern bool be_very_verbose; extern void append_reg_usage(FILE *, rtx_insn *); + + extern bool dump_reg_track; + void append_reg_cache (FILE * f, rtx_insn * insn); + const char *p; int c; #ifdef ASSEMBLER_DIALECT @@ -3784,6 +3788,8 @@ output_asm_insn (const char *templ, rtx *operands) if (be_very_verbose) append_reg_usage(asm_out_file, current_insn); + if (dump_reg_track) + append_reg_cache(asm_out_file, current_insn); /* Write out the variable names for operands, if we know them. */ if (flag_verbose_asm) diff --git a/gcc/passes.c b/gcc/passes.c index b216ee028245..1d53bb23b1b0 100644 --- gcc/passes.c +++ gcc/passes.c @@ -2284,7 +2284,7 @@ void dump_insns(char const * name) if (!set) continue; - if (CONST_PLUS_PIC_REG_CONST_UNSPEC_P(SET_SRC(set)) && MEM_P(SET_DEST(set))) + if (amiga_is_const_pic_ref(SET_SRC(set)) && MEM_P(SET_DEST(set))) debug_rtx(insn); } #endif From 219a2963be09c8bf789e875cefc55520a195d44a Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 10 Dec 2017 21:04:22 +0100 Subject: [PATCH 272/303] fix flag_pic handling --- gcc/config/m68k/amigaos.c | 2 +- gcc/config/m68k/m68k.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 298bcb18300c..1fe7d09b0142 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -826,7 +826,7 @@ int amiga_is_const_pic_ref (const_rtx cnst) { if (flag_pic < 3) - return true; + return false; int r = _amiga_is_const_pic_ref (cnst); // fprintf(stderr, r ? "valid pic: " : "invalid pic: "); // debug_rtx(cnst); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index a655ed8476bb..0a67f320bc1d 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2173,6 +2173,8 @@ m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p) struct m68k_address address; #ifdef TARGET_AMIGA + if (MEM_P(x)) + return false; /* SBF: the baserel(32) const plus pic_ref, symbol is an address. */ if (amiga_is_const_pic_ref(x)) return true; From 4c1164092dea34f47a66606c8962bc9b053ed650 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sun, 10 Dec 2017 21:47:42 +0100 Subject: [PATCH 273/303] fix mode handling in register tracking --- gcc/bbb-opts.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index dca287181b3a..32ef3ddde253 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -142,6 +142,8 @@ class track_var case CONST_DOUBLE: case SYMBOL_REF: case LABEL_REF: + if (GET_MODE(x) != dstMode) + return false; /* these can be used directly. */ *z = x; return true; @@ -152,7 +154,7 @@ class track_var /* try to expand the register. */ if (v) { - if (GET_MODE(v) != VOIDmode && dstMode != GET_MODE(v)) + if (dstMode != GET_MODE(v)) return false; *mask |= mask[REGNO(x)]; @@ -286,7 +288,7 @@ class track_var if (regno >= FIRST_PSEUDO_REGISTER) return; - value[regno] = gen_rtx_CONST_INT (VOIDmode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); + value[regno] = gen_rtx_CONST_INT (SImode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); mask[regno] = FIRST_PSEUDO_REGISTER; } From 50f74c0693d7b285ec06e3d0b12d0acb5a966a2d Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 11 Dec 2017 09:18:02 +0100 Subject: [PATCH 274/303] fix compare handling in register tracking --- gcc/bbb-opts.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 32ef3ddde253..faf69739db8d 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -142,8 +142,6 @@ class track_var case CONST_DOUBLE: case SYMBOL_REF: case LABEL_REF: - if (GET_MODE(x) != dstMode) - return false; /* these can be used directly. */ *z = x; return true; @@ -154,7 +152,7 @@ class track_var /* try to expand the register. */ if (v) { - if (dstMode != GET_MODE(v)) + if (dstMode != GET_MODE(v) && GET_CODE(v) != CONST_INT) return false; *mask |= mask[REGNO(x)]; @@ -289,7 +287,7 @@ class track_var return; value[regno] = gen_rtx_CONST_INT (SImode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); - mask[regno] = FIRST_PSEUDO_REGISTER; + mask[regno] = 1<assign (track); + if (ii.is_compare ()) + continue; + int dregno = ii.get_dst_regno (); track->clear (dregno, index); unsigned def = ii.get_def () & 0xffffff; track->clear_for_mask (def, index); - if (ii.is_compare ()) - continue; - if (ii.is_call ()) { track->clear_aftercall (index); From ed451fd6c28cdbca52f247c6719996a3b612c207 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 11 Dec 2017 10:13:33 +0100 Subject: [PATCH 275/303] fix mode handling b/w/l --- gcc/bbb-opts.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index faf69739db8d..676201619747 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -149,20 +149,24 @@ class track_var case REG: { rtx v = value[REGNO(x)]; + unsigned mr = mask[REGNO(x)]; /* try to expand the register. */ if (v) { - if (dstMode != GET_MODE(v) && GET_CODE(v) != CONST_INT) + if (dstMode != GET_MODE(v) && (GET_CODE(v) != CONST_INT || mr == (1<= FIRST_PSEUDO_REGISTER) return; - value[regno] = gen_rtx_CONST_INT (SImode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); + value[regno] = gen_rtx_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); mask[regno] = 1<clear (dregno, index); + track->clear (ii.get_mode(), dregno, index); unsigned def = ii.get_def () & 0xffffff; track->clear_for_mask (def, index); From dfad986c2f43b33e98dbc2b70a4058b8cf771a37 Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 11 Dec 2017 10:52:23 +0100 Subject: [PATCH 276/303] fix mode handling --- gcc/bbb-opts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 676201619747..e56e38ba73e0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -290,7 +290,7 @@ class track_var if (regno >= FIRST_PSEUDO_REGISTER) return; - value[regno] = gen_rtx_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); + value[regno] = gen_rtx_raw_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); mask[regno] = 1< Date: Mon, 11 Dec 2017 11:29:39 +0100 Subject: [PATCH 277/303] treat SFmode as SImode for normal regs --- gcc/bbb-opts.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index e56e38ba73e0..f54fb54d4405 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -153,7 +153,7 @@ class track_var /* try to expand the register. */ if (v) { - if (dstMode != GET_MODE(v) && (GET_CODE(v) != CONST_INT || mr == (1<= FIRST_PSEUDO_REGISTER) return; + if (mode == SFmode && regno < 16) + mode = SImode; + if (!extend (&value[regno], &mask[regno], mode, x)) { clear (mode, regno, index); @@ -290,8 +292,10 @@ class track_var if (regno >= FIRST_PSEUDO_REGISTER) return; - value[regno] = gen_rtx_raw_CONST_INT (mode, 0x100000000000000LL | ((long long int) (regno) << 32) | index); - mask[regno] = 1<clear (ii.get_mode(), dregno, index); + track->clear (ii.get_mode (), dregno, index); unsigned def = ii.get_def () & 0xffffff; track->clear_for_mask (def, index); @@ -4628,9 +4632,9 @@ namespace bool ispicref = false; // fix add PLUS/MINUS into the unspec offset if (GET_CODE(*src) == PLUS || GET_CODE(*src) == MINUS) - ispicref = amiga_is_const_pic_ref(XEXP(*src, 0)); + ispicref = amiga_is_const_pic_ref (XEXP(*src, 0)); else - ispicref = amiga_is_const_pic_ref(*src); + ispicref = amiga_is_const_pic_ref (*src); if (ispicref) { From b9eb7c80c772836b151ec2ae333c15d1ea744e18 Mon Sep 17 00:00:00 2001 From: fautomat Date: Mon, 11 Dec 2017 12:06:10 +0100 Subject: [PATCH 278/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e90d802ff727..a8c69c9addb5 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171203-234342 +20171211-120610 From 7b5b41278acb1bf3ca163b4adab55c08994cea6d Mon Sep 17 00:00:00 2001 From: bebbo Date: Mon, 11 Dec 2017 23:26:17 +0100 Subject: [PATCH 279/303] do not use hoist with -Os use also pre --- gcc/gcse.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gcc/gcse.c b/gcc/gcse.c index 5b2c96ecb5a6..f74e733f9337 100644 --- gcc/gcse.c +++ gcc/gcse.c @@ -4075,7 +4075,9 @@ pass_rtl_pre::gate (function *fun) { return optimize > 0 && flag_gcse && !fun->calls_setjmp +#ifndef TARGET_AMIGA && optimize_function_for_speed_p (fun) +#endif && dbg_cnt (pre); } @@ -4118,6 +4120,9 @@ class pass_rtl_hoist : public rtl_opt_pass bool pass_rtl_hoist::gate (function *) { +#ifdef TARGET_AMIGA + return false; +#else return optimize > 0 && flag_gcse && !cfun->calls_setjmp /* It does not make sense to run code hoisting unless we are optimizing @@ -4125,6 +4130,7 @@ pass_rtl_hoist::gate (function *) bigger if we did PRE (when optimizing for space, we don't run PRE). */ && optimize_function_for_size_p (cfun) && dbg_cnt (hoist); +#endif } } // anon namespace From 96f443e1846b944a8a665d0408574691dcca3259 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 12 Dec 2017 18:25:13 +0100 Subject: [PATCH 280/303] fix g++ executable dependency to install-cpp --- gcc/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2871c5794c4b..4aedf54bab12 100644 --- gcc/Makefile.in +++ gcc/Makefile.in @@ -3271,7 +3271,7 @@ endif install-strip: install # Handle cpp installation. -install-cpp: installdirs cpp$(exeext) +install-cpp: installdirs cpp$(exeext) all.cross -if test "$(enable_as_accelerator)" != "yes" ; then \ rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \ From d42099d1dc94abdec1291e32149c77e2ec1533d0 Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 12 Dec 2017 18:25:57 +0100 Subject: [PATCH 281/303] fix handling SIGN_EXTEND in opt_auto_inc --- gcc/bbb-opts.c | 2 +- gcc/config/m68k/amigaos.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index f54fb54d4405..585e719c2d5c 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1021,7 +1021,7 @@ insn_info::make_post_inc (int regno) if (src_op && get_src_mem_regno () == regno) { - if (src_op == NEG || src_op == NOT) + if (src_op == NEG || src_op == NOT || src_op == SIGN_EXTEND) mem = XEXP(mem, 0); else mem = XEXP(mem, 1); diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 1fe7d09b0142..60779c6579fc 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -939,7 +939,7 @@ amigaos_legitimate_src (rtx src) if (GET_CODE(op) == MINUS || GET_CODE(op) == PLUS) { rtx x = XEXP(op, 0); - if (GET_CODE(x) == NOT || GET_CODE(x) == NEG) + if (GET_CODE(x) == NOT || GET_CODE(x) == NEG || GET_CODE(x) == SIGN_EXTEND) { rtx reg = XEXP(x, 0); if (!REG_P(reg)) From c7ef0dc43dc68aebf4d27df6749c3a09b054d6e0 Mon Sep 17 00:00:00 2001 From: fautomat Date: Tue, 12 Dec 2017 19:07:22 +0100 Subject: [PATCH 282/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a8c69c9addb5..8f1a6c8420aa 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171211-120610 +20171212-190722 From 8b8789f06d99d60e60727b5a51690538d6dc403d Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 19 Dec 2017 16:51:50 +0100 Subject: [PATCH 283/303] do not deduplicate jump tables with 68000 since the 8 bits pcrel offset might be to small --- gcc/cfgcleanup.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 6e92d4cdde22..fddd9dd25458 100644 --- gcc/cfgcleanup.c +++ gcc/cfgcleanup.c @@ -2001,6 +2001,14 @@ try_crossjump_to_edge (int mode, edge e1, edge e2, { rtx_insn *insn; +#ifdef TARGET_AMIGA + /* + * we need replicated labels, if the labels are too far away, + * since on 68000 there are only 8 bits for the offset. + */ + if (TARGET_68020 || TARGET_68040) +#endif + /* Replace references to LABEL1 with LABEL2. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { @@ -2016,8 +2024,12 @@ try_crossjump_to_edge (int mode, edge e1, edge e2, /* Avoid splitting if possible. We must always split when SRC2 has EH predecessor edges, or we may end up with basic blocks with both normal and EH predecessor edges. */ - if (newpos2 == BB_HEAD (src2) + if ((newpos2 == BB_HEAD (src2) && !(EDGE_PRED (src2, 0)->flags & EDGE_EH)) +#ifdef TARGET_AMIGA + || (!TARGET_68020 && !TARGET_68040) +#endif + ) redirect_to = src2; else { From 8a91b7265bab01a1011c8f153323732d9eee48cf Mon Sep 17 00:00:00 2001 From: bebbo Date: Tue, 19 Dec 2017 18:34:20 +0100 Subject: [PATCH 284/303] fix last patch --- gcc/cfgcleanup.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index fddd9dd25458..378b1fc595bb 100644 --- gcc/cfgcleanup.c +++ gcc/cfgcleanup.c @@ -2006,7 +2006,8 @@ try_crossjump_to_edge (int mode, edge e1, edge e2, * we need replicated labels, if the labels are too far away, * since on 68000 there are only 8 bits for the offset. */ - if (TARGET_68020 || TARGET_68040) + if (!TARGET_68020 && !TARGET_68040) + return false; #endif /* Replace references to LABEL1 with LABEL2. */ @@ -2026,9 +2027,6 @@ try_crossjump_to_edge (int mode, edge e1, edge e2, normal and EH predecessor edges. */ if ((newpos2 == BB_HEAD (src2) && !(EDGE_PRED (src2, 0)->flags & EDGE_EH)) -#ifdef TARGET_AMIGA - || (!TARGET_68020 && !TARGET_68040) -#endif ) redirect_to = src2; else From 490ff33de1b66b808166de62b512e321fb412918 Mon Sep 17 00:00:00 2001 From: fautomat Date: Tue, 19 Dec 2017 19:03:07 +0100 Subject: [PATCH 285/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 8f1a6c8420aa..8426e3db7f19 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171212-190722 +20171219-190306 From 775d5c86463a8acca838702ce6e5e7d97a5ca102 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 21 Dec 2017 19:19:07 +0100 Subject: [PATCH 286/303] support section switching and provide the current var_decl --- gcc/varasm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/gcc/varasm.c b/gcc/varasm.c index b65f29c13a46..8ead5ec3fcbb 100644 --- gcc/varasm.c +++ gcc/varasm.c @@ -252,7 +252,6 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *), sect->unnamed.callback = callback; sect->unnamed.data = data; sect->unnamed.next = unnamed_sections; - unnamed_sections = sect; return sect; } @@ -2228,11 +2227,17 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, else { /* Special-case handling of vtv comdat sections. */ - if (sect->named.name + if ((sect->common.flags & SECTION_STYLE_MASK) == SECTION_NAMED && sect->named.name && (strcmp (sect->named.name, ".vtable_map_vars") == 0)) handle_vtv_comdat_section (sect, decl); else - switch_to_section (sect); + { +#ifdef TARGET_AMIGA + if ((sect->common.flags & SECTION_STYLE_MASK) == SECTION_NAMED) + sect->named.decl = decl; +#endif + switch_to_section (sect); + } if (align > BITS_PER_UNIT) ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); assemble_variable_contents (decl, name, dont_output_data); @@ -4962,7 +4967,7 @@ output_constructor_regular_field (oc_local_state *local) if each element has the proper size. */ if (local->field != NULL_TREE || local->index != NULL_TREE) { - if (fieldpos > local->total_bytes) + if (fieldpos >= local->total_bytes) { assemble_zeros (fieldpos - local->total_bytes); local->total_bytes = fieldpos; From 21ecb9edff4c412a373ff9c1d3cb0ddc1d2ffdb9 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 21 Dec 2017 19:23:02 +0100 Subject: [PATCH 287/303] added support for __chip, __fast and __far attributes --- gcc/config/m68k/amigaos.c | 207 +++++++++++------------------------------- gcc/config/m68k/amigaos.h | 5 +- gcc/config/m68k/m68k.c | 7 +- gcc/config/m68k/m68kamigaos.h | 14 ++- 4 files changed, 72 insertions(+), 161 deletions(-) diff --git a/gcc/config/m68k/amigaos.c b/gcc/config/m68k/amigaos.c index 60779c6579fc..28d20a980978 100644 --- gcc/config/m68k/amigaos.c +++ gcc/config/m68k/amigaos.c @@ -52,152 +52,6 @@ //int amiga_declare_object; #if 0 -static int amigaos_put_in_text (tree); -static rtx gen_stack_management_call (rtx, rtx, const char *); - -/* Baserel support. */ - -/* Does operand (which is a symbolic_operand) live in text space? If - so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. - - This function is used in base relative code generation. */ - -int -read_only_operand (rtx operand) - { - if (GET_CODE (operand) == CONST) - operand = XEXP (XEXP (operand, 0), 0); - if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); - return 1; - } - -/* Choose the section to use for DECL. RELOC is true if its value contains - any relocatable expression. */ - -void -amigaos_select_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED, - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) - { - // if (TREE_CODE (decl) == STRING_CST) -// { -//// flag_writable_strings /data_section not in gcc4, -////make life easy and put to same section -//// if (! flag_writable_strings) -//// readonly_data_section (); -//// else -// //data_section (); -// } -// else if (TREE_CODE (decl) == VAR_DECL) -// { -// if (TREE_READONLY (decl) -// && ! TREE_THIS_VOLATILE (decl) -// && DECL_INITIAL (decl) -// && (DECL_INITIAL (decl) == error_mark_node -// || TREE_CONSTANT (DECL_INITIAL (decl))) -// && (!flag_pic || (flag_pic<3 && !reloc) -// || SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))) -// readonly_data_section (); -// else -// data_section (); -// } -// else if ((!flag_pic || (flag_pic<3 && !reloc)) && DECL_P(decl) -// && SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0))) -// readonly_data_section (); -// else - //data_section (); - } - -/* This function is used while generating a base relative code. - It returns 1 if a decl is not relocatable, i. e., if it can be put - in the text section. - Currently, it's very primitive: it just checks if the object size - is less than 4 bytes (i. e., if it can hold a pointer). It also - supports arrays and floating point types. */ - -static int -amigaos_put_in_text (tree decl) - { - tree type = TREE_TYPE (decl); - if (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); - return (TREE_INT_CST_ELT(TYPE_SIZE (type), 1) == 0 - && TREE_INT_CST_LOW (TYPE_SIZE (type)) < 32) - || FLOAT_TYPE_P (type); - } - -/* Record properties of a DECL into the associated SYMBOL_REF. */ - -void -amigaos_encode_section_info (tree decl, rtx rtl, int first) - { - default_encode_section_info (decl, rtl, first); - - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - if (TREE_CODE (decl) == FUNCTION_DECL) // huh seem do same. not in gcc4 flag_writable_strings - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - else - { - if ((MEM_READONLY_P (rtl) && !MEM_VOLATILE_P (rtl) - && (flag_pic<3 || (TREE_CODE (decl) == STRING_CST - ) - || amigaos_put_in_text (decl))) - || (TREE_CODE (decl) == VAR_DECL - && DECL_SECTION_NAME (decl) != NULL)) - SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; - } - } - - -/* Attributes support. */ - -#define AMIGA_CHIP_SECTION_NAME ".datachip" - -/* Handle a "chip" attribute; - arguments as in struct attribute_spec.handler. */ - -tree -amigaos_handle_decl_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) - { - if (TREE_CODE (*node) == VAR_DECL) - { - if (is_attribute_p ("chip", name)) -#ifdef TARGET_ASM_NAMED_SECTION - { - if (! TREE_STATIC (*node) && ! DECL_EXTERNAL (*node)) - error ("`chip' attribute cannot be specified for local variables"); - else - { - /* The decl may have already been given a section attribute from - a previous declaration. Ensure they match. */ - if (DECL_SECTION_NAME (*node) == NULL_TREE) - DECL_SECTION_NAME (*node) = - build_string (strlen (AMIGA_CHIP_SECTION_NAME) + 1, - AMIGA_CHIP_SECTION_NAME); - else if (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (*node)), - AMIGA_CHIP_SECTION_NAME) != 0) - { - error_with_decl (*node, - "`chip' for `%s' conflicts with previous declaration"); - } - } - } -#else - error ("`chip' attribute is not supported for this target"); -#endif - } - else - { - warning (OPT_Wattributes, "`%s' attribute only applies to variables", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; - } //----- from 68k.c start @@ -607,6 +461,31 @@ amigaos_comp_type_attributes (const_tree type1, const_tree type2) return 0; } + else + { + tree attrs1 = TYPE_ATTRIBUTES(type1); + + tree chip1 = lookup_attribute("chip", attrs1); + tree fast1 = lookup_attribute("fast", attrs1); + tree far1 = lookup_attribute("far", attrs1); + + tree attrs2 = TYPE_ATTRIBUTES(type2); + + tree chip2 = lookup_attribute("chip", attrs2); + tree fast2 = lookup_attribute("fast", attrs2); + tree far2 = lookup_attribute("far", attrs2); + + if (chip1) + return chip2 && !fast2 && !far2; + + if (fast1) + return !chip2 && fast2 && !far2; + + if (far1) + return !chip2 && !fast2 && far2; + + return !chip2 && !fast2 && !far2; + } return 1; } /* end-GG-local */ @@ -689,7 +568,7 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI } else { - if (is_attribute_p ("chip", name)) + if (is_attribute_p ("chip", name) || is_attribute_p ("fast", name) || is_attribute_p ("far", name)) { // OK } @@ -707,6 +586,8 @@ amigaos_handle_type_attribute (tree *node, tree name, tree args, int flags ATTRI } #define AMIGA_CHIP_SECTION_NAME ".datachip" +#define AMIGA_FAST_SECTION_NAME ".datafast" +#define AMIGA_FAR_SECTION_NAME ".datafar" void amiga_insert_attribute (tree decl, tree * attr) @@ -716,28 +597,37 @@ amiga_insert_attribute (tree decl, tree * attr) tree name = TREE_PURPOSE(*attr); - if (is_attribute_p("chip", name)) + if (is_attribute_p("chip", name) || is_attribute_p("far", name) || is_attribute_p("fast", name)) { if (!TREE_TYPE(decl) == VAR_DECL) { - error ("`chip' attribute can only be specified for variables"); + error ("`%s' attribute can only be specified for variables", IDENTIFIER_POINTER(name)); return; } if (! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)) { - error ("`chip' attribute cannot be specified for local variables"); + error ("`%s' attribute cannot be specified for local variables", IDENTIFIER_POINTER(name)); return; } + + char const * section_name; + if (is_attribute_p("chip", name)) + section_name = AMIGA_CHIP_SECTION_NAME; + else if (is_attribute_p("fast", name)) + section_name = AMIGA_FAST_SECTION_NAME; + else if (is_attribute_p("far", name)) + section_name = AMIGA_FAR_SECTION_NAME; + + /* The decl may have already been given a section attribute from a previous declaration. Ensure they match. */ if (DECL_SECTION_NAME (decl) == NULL) - warning (OPT_Wattributes, "`%s' attribute is not yet supported", IDENTIFIER_POINTER(name)); -// set_decl_section_name(decl, AMIGA_CHIP_SECTION_NAME); - else if (strcmp (DECL_SECTION_NAME (decl), AMIGA_CHIP_SECTION_NAME) ) + set_decl_section_name(decl, section_name); + else if (strcmp (DECL_SECTION_NAME (decl), section_name) ) { error_at (DECL_SOURCE_LOCATION(decl), - "`chip' attribute conflicts with previous declaration"); + "`%s' attribute conflicts with previous declaration", IDENTIFIER_POINTER(name)); } } else @@ -763,11 +653,16 @@ amigaos_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *tota /* Output assembly to switch to section NAME with attribute FLAGS. */ #ifndef TARGET_AMIGAOS_VASM extern void -amiga_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) +amiga_named_section (const char *name, unsigned int flags, tree decl ) { + // only one code section - TODO: with amiga hunk this is no longer mandatory. if (0 == strncmp (".text", name, 5)) name = ".text"; - fprintf (asm_out_file, "\t%s\n", name); + + if (0 == strncmp(".data", name, 5) && (!DECL_INITIAL (decl) || initializer_zerop (DECL_INITIAL (decl)))) + fprintf (asm_out_file, "\t.bss%s\n", name + 5); + else + fprintf (asm_out_file, "\t%s\n", name); } #else extern void diff --git a/gcc/config/m68k/amigaos.h b/gcc/config/m68k/amigaos.h index 723c36969ad1..1b60ed633a3a 100644 --- gcc/config/m68k/amigaos.h +++ gcc/config/m68k/amigaos.h @@ -118,7 +118,8 @@ Boston, MA 02111-1307, USA. */ N_("Do not restore a4 in all functions") } -/* Support sections in chip memory, currently '.datachip' only. */ +/* Support sections in chip, fast memory, currently '.datachip', '.datafast' + * and '.datafar' to abs addressing with baserel. */ extern void amiga_named_section (const char *name, unsigned int flags, tree decl); @@ -445,6 +446,8 @@ while (0) #define SUBTARGET_ATTRIBUTES \ { "asmregs", 0, 0, false, false, false, 0, true }, \ { "chip", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \ + { "fast", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \ + { "far", 0, 0, false, true, false, amigaos_handle_type_attribute, false }, \ { "saveds", 0, 0, false, true, true, amigaos_handle_type_attribute, false }, \ { "regparm", 1, 1, false, true, true, amigaos_handle_type_attribute,\ true }, \ diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 0a67f320bc1d..85ed75e9fce7 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2534,8 +2534,13 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, /* SBF: Does the symbol use common or bss and qualifies for pic_reg? * Do not ref to .text via pic_reg! */ - if (GET_CODE (orig) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P(orig) && decl && (DECL_COMMON (decl) || bss_initializer_p (decl))) + char const * section = decl ? DECL_SECTION_NAME(decl) : 0; + if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig) && decl + && !decl->common.typed.base.readonly_flag + && !decl->decl_with_vis.in_text_section && !section) { +// fprintf(stderr, "(a4) for: %s\n", decl->decl_minimal.name->identifier.id.str); + /* SBF: unfortunately using the wrapped symbol without MEM does not work. * The pic_ref reference gets decomposed and leads to no working code. */ diff --git a/gcc/config/m68k/m68kamigaos.h b/gcc/config/m68k/m68kamigaos.h index 43ffcd0add39..83d1acb9d1e3 100644 --- gcc/config/m68k/m68kamigaos.h +++ gcc/config/m68k/m68kamigaos.h @@ -227,13 +227,19 @@ amiga_declare_object = 0 /* end of stuff from m68kv4.h */ #ifndef TARGET_AMIGAOS_VASM -#ifndef BSS_SECTION_ASM_OP +#undef BSS_SECTION_ASM_OP #define BSS_SECTION_ASM_OP "\t.bss" -#endif #else #define BSS_SECTION_ASM_OP "\tsection\tbss" #endif +#ifndef TARGET_AMIGAOS_VASM +#undef DATA_SECTION_ASM_OP +#define DATA_SECTION_ASM_OP "\t.data" +#else +#define DATA_SECTION_ASM_OP "\tsection\tdata" +#endif + #ifndef ASM_OUTPUT_ALIGNED_BSS #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) @@ -252,6 +258,8 @@ amiga_declare_object = 0 do \ { \ builtin_define ("__chip=__attribute__((__chip__))"); \ + builtin_define ("__fast=__attribute__((__fast__))"); \ + builtin_define ("__far=__attribute__((__far__))"); \ builtin_define ("__saveds=__attribute__((__saveds__))"); \ builtin_define ("__interrupt=__attribute__((__interrupt__))"); \ builtin_define ("__stackext=__attribute__((__stackext__))"); \ @@ -360,7 +368,7 @@ if (target_flags & (MASK_RESTORE_A4|MASK_ALWAYS_RESTORE_A4)) \ #undef ASM_SPEC #ifndef TARGET_AMIGAOS_VASM #define ASM_SPEC \ - "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" + "%(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc} %{!msmall-code:-S}" #else #define ASM_SPEC \ "-gas -esc -ldots -Fhunk -quiet %(asm_cpu) %(asm_cpu_default) %{msmall-code:-sc}" From c28c2cf8d727bb5bd0a1e98e9c9ca5c56635420f Mon Sep 17 00:00:00 2001 From: fautomat Date: Thu, 21 Dec 2017 19:50:03 +0100 Subject: [PATCH 288/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 8426e3db7f19..2d76043c1dd3 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171219-190306 +20171221-195003 From 40681c48c17fade42d96ffc1f405c2cc25bd7527 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 23 Dec 2017 11:07:32 +0100 Subject: [PATCH 289/303] access DECL stuff only if it is a SYMBOL_REF --- gcc/config/m68k/m68k.c | 7 +++---- gcc/config/m68k/m68k.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 85ed75e9fce7..d6accd3bfd8d 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2529,17 +2529,16 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, #ifdef TARGET_AMIGA else { - tree decl = SYMBOL_REF_DECL (orig); /* SBF: Does the symbol use common or bss and qualifies for pic_reg? * Do not ref to .text via pic_reg! */ - char const * section = decl ? DECL_SECTION_NAME(decl) : 0; - if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig) && decl + tree decl; + if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig) + && (decl = SYMBOL_REF_DECL (orig)) && !(DECL_SECTION_NAME(decl)) && !decl->common.typed.base.readonly_flag && !decl->decl_with_vis.in_text_section && !section) { -// fprintf(stderr, "(a4) for: %s\n", decl->decl_minimal.name->identifier.id.str); /* SBF: unfortunately using the wrapped symbol without MEM does not work. * The pic_ref reference gets decomposed and leads to no working code. diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 200f07ef63a4..6cdc635d4df3 100644 --- gcc/config/m68k/m68k.h +++ gcc/config/m68k/m68k.h @@ -620,11 +620,11 @@ __transfer_from_trampoline () \ #define REGNO_OK_FOR_INDEX_P(REGNO) \ (INT_REGNO_P (REGNO) \ - || INT_REGNO_P (reg_renumber[REGNO])) + || (reg_renumber && INT_REGNO_P (reg_renumber[REGNO]))) #define REGNO_OK_FOR_BASE_P(REGNO) \ (ADDRESS_REGNO_P (REGNO) \ - || ADDRESS_REGNO_P (reg_renumber[REGNO])) + || (reg_renumber && ADDRESS_REGNO_P (reg_renumber[REGNO]))) #define REGNO_OK_FOR_INDEX_NONSTRICT_P(REGNO) \ (INT_REGNO_P (REGNO) \ From 8b9a647f47952ea1411a54e51f5406fb79a3e30d Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 23 Dec 2017 11:08:23 +0100 Subject: [PATCH 290/303] more compatible way to apply register renaming --- gcc/bbb-opts.c | 64 ++++++++++++++++++---------------------------------------- 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 585e719c2d5c..432c9bb4bbd3 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -1452,11 +1452,11 @@ copy_reg (rtx reg, int newregno) } /* Rename the register plus track all locs to undo these changes. */ -static void -temp_reg_rename (std::vector > & loc, rtx x, unsigned oldregno, unsigned newregno) +static rtx +find_reg_by_no (rtx x, unsigned oldregno) { if (!x) - return; + return 0; RTX_CODE code = GET_CODE(x); @@ -1469,27 +1469,25 @@ temp_reg_rename (std::vector > & loc, rtx x, unsigned oldr if (REG_P(y)) { if (REGNO(y) == oldregno) - { - rtx z = copy_reg (y, newregno); - loc.push_back (std::make_pair (&XEXP(x, i), y)); - XEXP(x, i) = z; - } + return y; } else - temp_reg_rename (loc, y, oldregno, newregno); + { + rtx r = find_reg_by_no (y, oldregno); + if (r) + return r; + } } else if (fmt[i] == 'E') for (int j = XVECLEN (x, i) - 1; j >= 0; j--) { rtx z = XVECEXP(x, i, j); - if (GET_CODE(z) == CLOBBER) - { - /* workaround for shared clobbers. */ - XVECEXP(x, i, j) = z = gen_rtx_CLOBBER(GET_MODE(z), XEXP(z, 0)); - } - temp_reg_rename (loc, z, oldregno, newregno); + rtx r = find_reg_by_no(z, oldregno); + if (r) + return r; } } + return 0; } /* @@ -2454,45 +2452,27 @@ opt_reg_rename (void) /* check the renamed insns. */ std::vector positions; - std::vector > locs; - std::vector > patch; - bool ok = true; - - for (std::set::iterator i = found.begin (); ok && i != found.end (); ++i) + for (std::set::iterator i = found.begin (); i != found.end (); ++i) { insn_info & rr = infos[*i]; rtx_insn * insn = rr.get_insn (); - /* temp rename. */ - temp_reg_rename (locs, PATTERN (insn), oldregno, newregno); - if (!locs.empty ()) + /* get rename locations. */ + rtx from = find_reg_by_no(PATTERN (insn), oldregno); + if (from) { - if (insn_invalid_p (insn, 1)) - ok = false; - - /* undo temp change but keep loc and new register. */ - for (std::vector >::iterator j = locs.begin (); j != locs.end (); ++j) - { - patch.push_back (std::make_pair (j->first, *j->first)); - *j->first = j->second; - } + rtx to = gen_raw_REG(GET_MODE(from), newregno); + validate_replace_rtx_group(from, to, insn); positions.push_back (*i); - locs.clear (); } } - if (!ok) - { - cancel_changes (0); - continue; - } - if (!apply_change_group ()) continue; log ("(r) opt_reg_rename %s -> %s (%d locs, start at %d)\n", reg_names[oldregno], reg_names[newregno], - patch.size (), index); + positions.size (), index); if (be_verbose) { @@ -2502,10 +2482,6 @@ opt_reg_rename (void) fflush (stdout); } - /* apply all changes. */ - for (std::vector >::iterator j = patch.begin (); j != patch.end (); ++j) - *j->first = j->second; - return 1; } } From 3b4383bb016fb3c48ee7fbc30a9737370dc7d56b Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 23 Dec 2017 11:53:34 +0100 Subject: [PATCH 291/303] fix compile error - uups --- gcc/config/m68k/m68k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index d6accd3bfd8d..29e2e45df844 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -2537,7 +2537,7 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, if (GET_CODE (orig) == SYMBOL_REF && !orig->frame_related && !SYMBOL_REF_FUNCTION_P(orig) && (decl = SYMBOL_REF_DECL (orig)) && !(DECL_SECTION_NAME(decl)) && !decl->common.typed.base.readonly_flag - && !decl->decl_with_vis.in_text_section && !section) + && !decl->decl_with_vis.in_text_section) { /* SBF: unfortunately using the wrapped symbol without MEM does not work. From 5eb6023e66b9bdf3125e5381d11ac9992835f943 Mon Sep 17 00:00:00 2001 From: bebbo Date: Sat, 23 Dec 2017 11:54:08 +0100 Subject: [PATCH 292/303] fix inlined functions - removed extern --- gcc/config/m68k/math-68881.h | 62 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/gcc/config/m68k/math-68881.h b/gcc/config/m68k/math-68881.h index 6d9f8b2d4a1f..20a5037cc525 100644 --- gcc/config/m68k/math-68881.h +++ gcc/config/m68k/math-68881.h @@ -37,7 +37,7 @@ September 1993, Use #undef before HUGE_VAL instead of #ifdef/#endif. */ /* Changed by Ian Lance Taylor: - September 1994, use extern inline instead of static inline. */ + September 1994, use inline instead of static inline. */ #ifndef __math_68881 #define __math_68881 @@ -64,7 +64,7 @@ }) #endif -__inline extern double +__inline double sin (double x) { double value; @@ -75,7 +75,7 @@ sin (double x) return value; } -__inline extern double +__inline double cos (double x) { double value; @@ -86,7 +86,7 @@ cos (double x) return value; } -__inline extern double +__inline double tan (double x) { double value; @@ -97,7 +97,7 @@ tan (double x) return value; } -__inline extern double +__inline double asin (double x) { double value; @@ -108,7 +108,7 @@ asin (double x) return value; } -__inline extern double +__inline double acos (double x) { double value; @@ -119,7 +119,7 @@ acos (double x) return value; } -__inline extern double +__inline double atan (double x) { double value; @@ -130,7 +130,7 @@ atan (double x) return value; } -__inline extern double +__inline double atan2 (double y, double x) { double pi, pi_over_2; @@ -187,7 +187,7 @@ atan2 (double y, double x) } } -__inline extern double +__inline double sinh (double x) { double value; @@ -198,7 +198,7 @@ sinh (double x) return value; } -__inline extern double +__inline double cosh (double x) { double value; @@ -209,7 +209,7 @@ cosh (double x) return value; } -__inline extern double +__inline double tanh (double x) { double value; @@ -220,7 +220,7 @@ tanh (double x) return value; } -__inline extern double +__inline double atanh (double x) { double value; @@ -231,7 +231,7 @@ atanh (double x) return value; } -__inline extern double +__inline double exp (double x) { double value; @@ -242,7 +242,7 @@ exp (double x) return value; } -__inline extern double +__inline double expm1 (double x) { double value; @@ -253,7 +253,7 @@ expm1 (double x) return value; } -__inline extern double +__inline double log (double x) { double value; @@ -264,7 +264,7 @@ log (double x) return value; } -__inline extern double +__inline double log1p (double x) { double value; @@ -275,7 +275,7 @@ log1p (double x) return value; } -__inline extern double +__inline double log10 (double x) { double value; @@ -286,7 +286,7 @@ log10 (double x) return value; } -__inline extern double +__inline double sqrt (double x) { double value; @@ -297,13 +297,13 @@ sqrt (double x) return value; } -__inline extern double +__inline double hypot (double x, double y) { return sqrt (x*x + y*y); } -__inline extern double +__inline double pow (double x, double y) { if (x > 0) @@ -352,7 +352,7 @@ pow (double x, double y) } } -__inline extern double +__inline double fabs (double x) { double value; @@ -363,7 +363,7 @@ fabs (double x) return value; } -__inline extern double +__inline double ceil (double x) { int rounding_mode, round_up; @@ -385,7 +385,7 @@ ceil (double x) return value; } -__inline extern double +__inline double floor (double x) { int rounding_mode, round_down; @@ -408,7 +408,7 @@ floor (double x) return value; } -__inline extern double +__inline double rint (double x) { int rounding_mode, round_nearest; @@ -430,7 +430,7 @@ rint (double x) return value; } -__inline extern double +__inline double fmod (double x, double y) { double value; @@ -442,7 +442,7 @@ fmod (double x, double y) return value; } -__inline extern double +__inline double drem (double x, double y) { double value; @@ -454,7 +454,7 @@ drem (double x, double y) return value; } -__inline extern double +__inline double scalb (double x, int n) { double value; @@ -466,7 +466,7 @@ scalb (double x, int n) return value; } -__inline extern double +__inline double logb (double x) { double exponent; @@ -477,7 +477,7 @@ logb (double x) return exponent; } -__inline extern double +__inline double ldexp (double x, int n) { double value; @@ -489,7 +489,7 @@ ldexp (double x, int n) return value; } -__inline extern double +__inline double frexp (double x, int *exp) { double float_exponent; @@ -514,7 +514,7 @@ frexp (double x, int *exp) return mantissa; } -__inline extern double +__inline double modf (double x, double *ip) { double temp; From 443179daa5f06a569a4de7e62c431d787c066f86 Mon Sep 17 00:00:00 2001 From: fautomat Date: Sat, 23 Dec 2017 13:18:20 +0100 Subject: [PATCH 293/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2d76043c1dd3..e70e15403ebc 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171221-195003 +20171223-131819 From b5b76e646e60f561e56608ad1839013fcc04d3cc Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 29 Dec 2017 10:20:42 +0100 Subject: [PATCH 294/303] set -Os as default --- gcc/config.gcc | 1 + libgcc/config.host | 1 + 2 files changed, 2 insertions(+) diff --git a/gcc/config.gcc b/gcc/config.gcc index 0beee32c863c..59df5867053d 100644 --- gcc/config.gcc +++ gcc/config.gcc @@ -1955,6 +1955,7 @@ m68k*-*-amigaos*) extra_objs=amigaos.o extra_options="${extra_options} m68k/amigaos.opt" gnu_ld=yes + CFLAGS="-Os" ;; m68k*-*-netbsdelf*) default_m68k_cpu=68020 diff --git a/libgcc/config.host b/libgcc/config.host index c36e829a5025..0a88fa78c170 100644 --- libgcc/config.host +++ libgcc/config.host @@ -818,6 +818,7 @@ m32rle-*-linux*) ;; m68k-*-amiga*) tmake_file="$tmake_file m68k/t-glue m68k/t-floatlib soft-fp" + CFLAGS="-Os" # tmake_file="$tmake_file m68k/t-glue soft-fp" ;; m68k-*-elf* | fido-*-elf) From 734f944e12181b7fd69e0447f68f1be7fcd13822 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 29 Dec 2017 10:21:49 +0100 Subject: [PATCH 295/303] print insn before aborting --- gcc/emit-rtl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 0fcd9d95e5b4..b2a18e7e4188 100644 --- gcc/emit-rtl.c +++ gcc/emit-rtl.c @@ -2123,7 +2123,11 @@ change_address_1 (rtx memref, machine_mode mode, rtx addr, int validate, if (validate && !lra_in_progress) { if (reload_in_progress || reload_completed) - gcc_assert (memory_address_addr_space_p (mode, addr, as)); + { + bool r = memory_address_addr_space_p (mode, addr, as); + if (!r) debug_rtx(addr); + gcc_assert (r); + } else addr = memory_address_addr_space (mode, addr, as); } From 765a8c42eee2c949fc5d31b3e4693c8237bdb48b Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 29 Dec 2017 10:22:34 +0100 Subject: [PATCH 296/303] fix a check with -fbaserel(32) --- gcc/config/m68k/m68k.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 29e2e45df844..4533427db7a7 100644 --- gcc/config/m68k/m68k.c +++ gcc/config/m68k/m68k.c @@ -1982,10 +1982,12 @@ m68k_legitimate_constant_address_p (rtx x, unsigned int reach, bool strict_p) if (!CONSTANT_ADDRESS_P (x)) return false; - if (flag_pic + if (flag_pic && flag_pic < 3 && !(strict_p && TARGET_PCREL) && symbolic_operand (x, VOIDmode)) - return false; + { + return false; + } if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P && reach > 1) { From 44cf4734135f00e7949a431a308e5da436735300 Mon Sep 17 00:00:00 2001 From: bebbo Date: Fri, 29 Dec 2017 10:23:00 +0100 Subject: [PATCH 297/303] enable multilib --- gcc/config/m68k/t-amigaos | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gcc/config/m68k/t-amigaos b/gcc/config/m68k/t-amigaos index 112d5daa06fb..bf9c5279d04f 100755 --- gcc/config/m68k/t-amigaos +++ gcc/config/m68k/t-amigaos @@ -10,14 +10,6 @@ amigaos.o: $(srcdir)/config/m68k/amigaos.c $(CONFIG_H) #TARGET_LIBGCC2_CFLAGS = -mfixedstack -# Support for building multiple version of libgcc. - -LIBGCC_MULTI = .; \ - libb;@fbaserel \ - libm020;@m68020 \ - libb/libm020;@fbaserel@m68020 \ - libb32/libm020;@fbaserel32@m68020 - ### begin-GG-local: dynamic libraries # Extra objects that get compiled and linked to collect2 @@ -28,3 +20,9 @@ amigacollect2.o: amigacollect2.c $(CXX) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DA2IXDIR_PREFIX=\"$(prefix)/share/a2ixlibrary\" $< $(OUTPUT_OPTION) ### end-GG-local + +# Support for building multiple version of libgcc, libquadmath, libobjc and libstdc++-v3 +MULTILIB_OPTIONS = m68020 fbaserel/fbaserel32 +MULTILIB_DIRNAMES = libm020 libb libb32 +MULTILIB_EXTRA_OPTS = noixemul +MULTILIB_EXCEPTIONS = fbaserel32 \ No newline at end of file From e7906b06f6cba077f666b43dfa822c4117078a9a Mon Sep 17 00:00:00 2001 From: fautomat Date: Fri, 29 Dec 2017 10:52:57 +0100 Subject: [PATCH 298/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e70e15403ebc..1ba74cfc6d61 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171223-131819 +20171229-105257 From 20fa3b9980630cf21b2a19f6f26e276840e0c7d5 Mon Sep 17 00:00:00 2001 From: bebbo Date: Wed, 10 Jan 2018 20:37:20 +0100 Subject: [PATCH 299/303] refs #7: invalidate registers holding a memory referenc if a value is written to that memory reference --- gcc/bbb-opts.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 432c9bb4bbd3..ae824bbfbb1a 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -238,13 +238,38 @@ class track_var if (o) assign (o); else - for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { value[i] = 0; mask[i] = 0; } } + void + invalidate_mem(rtx dst) { + rtx z = 0; + unsigned m = 0; + if (extend(&z, &m, GET_MODE(dst), dst)) + { +// unsigned hit = 0; + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (rtx_equal_p(z, value[i])) + { + value[i] = 0; + mask[i] = 0; +// hit |= 1<value[i])) { value[i] = o->value[i] = 0; - mask[i] = mask[i] = 0; + mask[i] = 0; } } } @@ -3940,7 +3965,10 @@ track_regs () continue; if (dregno < 0) - continue; + { + track->invalidate_mem(SET_DEST(set)); + continue; + } // operation, autoinf or more than one register used: can't cache if (ii.get_src_op () || ii.get_src_autoinc () || ((ii.get_myuse () - 1) & ii.get_myuse ())) From 57be9251f4cb7adfd7850d21d7bd77d13474be32 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 11 Jan 2018 20:08:18 +0100 Subject: [PATCH 300/303] opt_elim_dead_assign checks now if some register contains a value already and uses that reg --- gcc/bbb-opts.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index ae824bbfbb1a..3235c84deb4b 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -223,10 +223,11 @@ class track_var *z = gen_rtx_MEM (GET_MODE(x), m); return true; } + default: + return false; } - return false; + break; } - default: return false; } @@ -245,27 +246,36 @@ class track_var } } + int find_alias(rtx src) + { + rtx z = 0; + unsigned m = 0; + if (extend(&z, &m, GET_MODE(src), src)) + { + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + // do not alias small int value from -128 ... 127 + if (rtx_equal_p(z, value[i]) && (GET_CODE(z) != CONST_INT || INTVAL(z) > 127 || INTVAL(z) < -128)) + return i; + } + } + return -1; + } void - invalidate_mem(rtx dst) { + invalidate_mem(rtx dst) + { rtx z = 0; unsigned m = 0; if (extend(&z, &m, GET_MODE(dst), dst)) { -// unsigned hit = 0; for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { if (rtx_equal_p(z, value[i])) { value[i] = 0; mask[i] = 0; -// hit |= 1<find_alias(src); + if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno()) + { + log ("(e) %d: replace load with %s\n", index, reg_names[aliasRegno]); + validate_change (ii.get_insn(), &SET_SRC(set), gen_rtx_REG(ii.get_mode(), aliasRegno), 0); + ++change_count; + } + } } } return change_count; From 03065de1585bae453567dbf1c2352794fac793d1 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 11 Jan 2018 20:09:01 +0100 Subject: [PATCH 301/303] reg rename may use the starting used register if it's dead there (Jim) --- gcc/bbb-opts.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 3235c84deb4b..2be2afe83c77 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -2332,6 +2332,10 @@ opt_reg_rename (void) /* get the mask for free registers. */ unsigned mask = ii.get_free_mask (); + /* the mask contains the current src register. Add this register to the mask if it's dead here. */ + if (ii.get_src_reg() && is_reg_dead(ii.get_src_regno(), index)) + mask |= ii.get_use(); + /* do not use a4 if compiling baserel */ if (flag_pic >= 3) mask &= ~(1 << PIC_REG); From 14767273a413e13794aeec098ee0c54acce1b9d4 Mon Sep 17 00:00:00 2001 From: bebbo Date: Thu, 11 Jan 2018 21:36:13 +0100 Subject: [PATCH 302/303] change register order - prefer ax over dx to avoid address calculation in dx regs, improve opt_elim_dead_assign() to eliminate self assignments --- gcc/bbb-opts.c | 50 ++++++++++++++++++++++++++++---------------------- gcc/config/m68k/m68k.h | 16 ++++++++++++++-- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/gcc/bbb-opts.c b/gcc/bbb-opts.c index 2be2afe83c77..9e989e9b1ec0 100755 --- gcc/bbb-opts.c +++ gcc/bbb-opts.c @@ -246,31 +246,32 @@ class track_var } } - int find_alias(rtx src) + int + find_alias (rtx src) { rtx z = 0; unsigned m = 0; - if (extend(&z, &m, GET_MODE(src), src)) + if (extend (&z, &m, GET_MODE(src), src)) { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { // do not alias small int value from -128 ... 127 - if (rtx_equal_p(z, value[i]) && (GET_CODE(z) != CONST_INT || INTVAL(z) > 127 || INTVAL(z) < -128)) + if (rtx_equal_p (z, value[i]) && (GET_CODE(z) != CONST_INT || INTVAL(z) > 127 || INTVAL(z) < -128)) return i; } } return -1; } void - invalidate_mem(rtx dst) + invalidate_mem (rtx dst) { rtx z = 0; unsigned m = 0; - if (extend(&z, &m, GET_MODE(dst), dst)) + if (extend (&z, &m, GET_MODE(dst), dst)) { for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; ++i) { - if (rtx_equal_p(z, value[i])) + if (rtx_equal_p (z, value[i])) { value[i] = 0; mask[i] = 0; @@ -279,7 +280,6 @@ class track_var } } - rtx get (unsigned regno) { @@ -1517,7 +1517,7 @@ find_reg_by_no (rtx x, unsigned oldregno) for (int j = XVECLEN (x, i) - 1; j >= 0; j--) { rtx z = XVECEXP(x, i, j); - rtx r = find_reg_by_no(z, oldregno); + rtx r = find_reg_by_no (z, oldregno); if (r) return r; } @@ -2333,8 +2333,8 @@ opt_reg_rename (void) unsigned mask = ii.get_free_mask (); /* the mask contains the current src register. Add this register to the mask if it's dead here. */ - if (ii.get_src_reg() && is_reg_dead(ii.get_src_regno(), index)) - mask |= ii.get_use(); + if (ii.get_src_reg () && is_reg_dead (ii.get_src_regno (), index)) + mask |= ii.get_use (); /* do not use a4 if compiling baserel */ if (flag_pic >= 3) @@ -2497,11 +2497,11 @@ opt_reg_rename (void) rtx_insn * insn = rr.get_insn (); /* get rename locations. */ - rtx from = find_reg_by_no(PATTERN (insn), oldregno); + rtx from = find_reg_by_no (PATTERN (insn), oldregno); if (from) { - rtx to = gen_raw_REG(GET_MODE(from), newregno); - validate_replace_rtx_group(from, to, insn); + rtx to = gen_raw_REG (GET_MODE(from), newregno); + validate_replace_rtx_group (from, to, insn); positions.push_back (*i); } @@ -3945,11 +3945,17 @@ track_regs () if (ii.is_compare ()) continue; - int dregno = ii.get_dst_regno (); - track->clear (ii.get_mode (), dregno, index); - unsigned def = ii.get_def () & 0xffffff; - track->clear_for_mask (def, index); + if (def) + { + // more than one register set? or mask from clobber? + if (((def - 1) & def) || !ii.get_dst_reg ()) + track->clear_for_mask (def, index); + } + // do not clear if self assigned + int dregno = ii.get_dst_regno (); + if (dregno != ii.get_src_regno ()) + track->clear (ii.get_mode (), dregno, index); if (ii.is_call ()) { @@ -3980,7 +3986,7 @@ track_regs () if (dregno < 0) { - track->invalidate_mem(SET_DEST(set)); + track->invalidate_mem (SET_DEST(set)); continue; } @@ -4031,7 +4037,7 @@ opt_elim_dead_assign (int blocked_regno) // check for redundant load if (ii.get_src_op () == 0 && ii.get_dst_reg () && ii.get_dst_regno () != blocked_regno - && !ii.is_myuse (ii.get_dst_regno ())) + && (!ii.is_myuse (ii.get_dst_regno ()) || ii.get_dst_regno () == ii.get_src_regno ())) { track_var * track = ii.get_track_var (); @@ -4055,11 +4061,11 @@ opt_elim_dead_assign (int blocked_regno) // is there a register holding that value? if (!ii.get_src_reg ()) { - int aliasRegno = track->find_alias(src); - if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno()) + int aliasRegno = track->find_alias (src); + if (aliasRegno >= 0 && aliasRegno != ii.get_dst_regno ()) { log ("(e) %d: replace load with %s\n", index, reg_names[aliasRegno]); - validate_change (ii.get_insn(), &SET_SRC(set), gen_rtx_REG(ii.get_mode(), aliasRegno), 0); + validate_change (ii.get_insn (), &SET_SRC(set), gen_rtx_REG (ii.get_mode (), aliasRegno), 0); ++change_count; } } diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 6cdc635d4df3..278b048ae237 100644 --- gcc/config/m68k/m68k.h +++ gcc/config/m68k/m68k.h @@ -378,13 +378,25 @@ along with GCC; see the file COPYING3. If not see /* Arg pointer. */ \ 1 } +#if 0 #define REG_ALLOC_ORDER \ { /* d0/d1/a0/a1 */ \ 0, 1, 8, 9, \ /* d2-d7 */ \ - 2, 3, 4, 5, 6, 7, \ + 2, 10, 3, 11, 4, 5, 6, 7, \ /* a2-a7/arg */ \ - 10, 11, 12, 13, 14, 15, 24, \ + 12, 13, 14, 15, 24, \ + /* fp0-fp7 */ \ + 16, 17, 18, 19, 20, 21, 22, 23\ +} +#endif +#define REG_ALLOC_ORDER \ +{ /* d0/d1/a0/a1 */ \ + 0, 8, 9, 1, \ + /* a2-a7 */ \ + 10, 11, 12, 13, 14, 15, \ + /* d2-d7/arg */ \ + 2, 3, 4, 5, 6, 7, 24, \ /* fp0-fp7 */ \ 16, 17, 18, 19, 20, 21, 22, 23\ } From 359713c99b0cbf7744ad3158929c53fb304e3ce4 Mon Sep 17 00:00:00 2001 From: fautomat Date: Thu, 11 Jan 2018 22:28:38 +0100 Subject: [PATCH 303/303] bump version DATESTAMP --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1ba74cfc6d61..97461d26bd27 100644 --- gcc/DATESTAMP +++ gcc/DATESTAMP @@ -1 +1 @@ -20171229-105257 +20180111-222838