diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/scodbx.h | 84 | ||||
-rw-r--r-- | gcc/config/i386/xm-dgux.h | 4 | ||||
-rw-r--r-- | gcc/config/i386/xm-sun.h | 21 | ||||
-rw-r--r-- | gcc/config/i386/xm-sysv3.h | 3 | ||||
-rw-r--r-- | gcc/config/ia64/ia64-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 34 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 10 | ||||
-rw-r--r-- | gcc/config/m32r/m32r.c | 4 | ||||
-rw-r--r-- | gcc/config/m32r/m32r.h | 7 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 39 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 3 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 3 | ||||
-rw-r--r-- | gcc/config/rs6000/altivec.md | 209 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 299 | ||||
-rw-r--r-- | gcc/config/rs6000/sysv4.h | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 158 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 18 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 352 | ||||
-rw-r--r-- | gcc/config/s390/tpf.h | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 4 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 44 | ||||
-rw-r--r-- | gcc/config/sh/symbian.c | 3 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 64 |
25 files changed, 990 insertions, 390 deletions
diff --git a/gcc/config/i386/scodbx.h b/gcc/config/i386/scodbx.h deleted file mode 100644 index 7da93053256..00000000000 --- a/gcc/config/i386/scodbx.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Definitions for Intel 386 running SCO Unix System V, - using dbx-in-coff encapsulation. - Copyright (C) 1992, 1995, 1996, 1999 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "i386/svr3dbx.h" - -/* Overridden defines for SCO systems from sco.h. */ - -/* By default, target has a 80387, uses IEEE compatible arithmetic, - and returns float values in the 387, ie, - (TARGET_80387 | TARGET_FLOAT_RETURNS_IN_80387) - - SCO's software emulation of a 387 fails to handle the `fucomp' - opcode. fucomp is only used when generating IEEE compliant code. - So don't make TARGET_IEEE_FP default for SCO. */ - -#undef TARGET_SUBTARGET_DEFAULT -#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS) - -/* Use crt1.o as a startup file and crtn.o as a closing file. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!r:%{!z:svr3.ifile%s}%{z:svr3z.ifile%s}}\ - %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}" - -/* Library spec, including SCO international language support. */ - -#undef LIB_SPEC -#define LIB_SPEC \ - "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} %{scointl:libintl.a%s} -lc" - -/* Specify predefined symbols in preprocessor. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem=svr3" - -#undef CPP_SPEC -#define CPP_SPEC "%(cpp_cpu) %{scointl:-DM_INTERNAT}" - -/* This spec is used for telling cpp whether char is signed or not. */ - -#undef SIGNED_CHAR_SPEC -#if DEFAULT_SIGNED_CHAR -#define SIGNED_CHAR_SPEC \ - "%{funsigned-char:-D__CHAR_UNSIGNED__ -D_CHAR_UNSIGNED}" -#else -#define SIGNED_CHAR_SPEC \ - "%{!fsigned-char:-D__CHAR_UNSIGNED__ -D_CHAR_UNSIGNED}" -#endif - -/* caller has to pop the extra argument passed to functions that return - structures. */ - -#undef RETURN_POPS_ARGS -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ - : (TARGET_RTD \ - && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ - == void_type_node))) ? (SIZE) \ - : 0) -/* On other 386 systems, the last line looks like this: - : (aggregate_value_p (TREE_TYPE (FUNTYPE))) ? GET_MODE_SIZE (Pmode) : 0) */ - -/* Handle #pragma pack. */ -#define HANDLE_SYSV_PRAGMA diff --git a/gcc/config/i386/xm-dgux.h b/gcc/config/i386/xm-dgux.h deleted file mode 100644 index 881c5c7be9d..00000000000 --- a/gcc/config/i386/xm-dgux.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Configuration for GCC for Intel i386 running DG/ux */ - -/* looks just like sysv4 for now */ -#include "xm-svr4.h" diff --git a/gcc/config/i386/xm-sun.h b/gcc/config/i386/xm-sun.h deleted file mode 100644 index 6c0f0a25630..00000000000 --- a/gcc/config/i386/xm-sun.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Configuration for GNU C-compiler for Intel 80386 running SunOS 4.0. - Copyright (C) 1988, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define USG diff --git a/gcc/config/i386/xm-sysv3.h b/gcc/config/i386/xm-sysv3.h deleted file mode 100644 index 9a655443ff5..00000000000 --- a/gcc/config/i386/xm-sysv3.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Configuration for GCC for Intel i386 running System V Release 3. */ - -#include "xm-svr3.h" diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index 19e1335b17e..ab5062c8c72 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -77,6 +77,7 @@ extern int ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *, enum machine_mode, tree, int); extern void ia64_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); +extern int ia64_function_arg_boundary (enum machine_mode, tree); extern void ia64_asm_output_external (FILE *, tree, const char *); #endif /* TREE_CODE */ diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index b51cc7a9408..5eed72144ef 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -3325,10 +3325,11 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, cum->fp_regs = fp_regs; } - /* Integral and aggregates go in general registers. If we have run out of - FR registers, then FP values must also go in general registers. This can - happen when we have a SFmode HFA. */ - else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS) + /* Integral and aggregates go in general registers. So do TFmode FP values. + If we have run out of FR registers, then other FP values must also go in + general registers. This can happen when we have a SFmode HFA. */ + else if (mode == TFmode || mode == TCmode + || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)) cum->int_regs = cum->words; /* If there is a prototype, then FP values go in a FR register when @@ -3351,6 +3352,31 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, } } +/* Arguments with alignment larger than 8 bytes start at the next even + boundary. On ILP32 HPUX, TFmode arguments start on next even boundary + even though their normal alignment is 8 bytes. See ia64_function_arg. */ + +int +ia64_function_arg_boundary (enum machine_mode mode, tree type) +{ + + if (mode == TFmode && TARGET_HPUX && TARGET_ILP32) + return PARM_BOUNDARY * 2; + + if (type) + { + if (TYPE_ALIGN (type) > PARM_BOUNDARY) + return PARM_BOUNDARY * 2; + else + return PARM_BOUNDARY; + } + + if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY) + return PARM_BOUNDARY * 2; + else + return PARM_BOUNDARY; +} + /* Variable sized types are passed by reference. */ /* ??? At present this is a GCC extension to the IA-64 ABI. */ diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 58304a9b366..aab51f83000 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1376,15 +1376,11 @@ do { \ /* If defined, a C expression that gives the alignment boundary, in bits, of an argument with the specified mode and type. */ -/* Arguments with alignment larger than 8 bytes start at the next even - boundary. See ia64_function_arg. */ +/* Return the alignment boundary in bits for an argument with a specified + mode and type. */ #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) ? (TYPE_ALIGN (TYPE) > 8 * BITS_PER_UNIT) \ - : (((((MODE) == BLKmode \ - ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \ - + UNITS_PER_WORD - 1) / UNITS_PER_WORD) > 1)) \ - ? 128 : PARM_BOUNDARY) + ia64_function_arg_boundary (MODE, TYPE) /* A C expression that is nonzero if REGNO is the number of a hard register in which function arguments are sometimes passed. This does *not* include diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 9e3404a1891..b5621568997 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -1591,8 +1591,8 @@ static struct m32r_frame_info zero_frame_info; The return address and frame pointer are treated separately. Don't consider them here. */ #define MUST_SAVE_REGISTER(regno, interrupt_p) \ -((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \ - && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p))) + ((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \ + && (regs_ever_live[regno] && (!call_really_used_regs[regno] || interrupt_p))) #define MUST_SAVE_FRAME_POINTER (regs_ever_live[FRAME_POINTER_REGNUM]) #define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM] || current_function_profile) diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 9befbeee570..d5aa56b82e6 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -633,6 +633,8 @@ extern enum m32r_sdata m32r_sdata; SUBTARGET_CALL_USED_REGISTERS \ } +#define CALL_REALLY_USED_REGISTERS CALL_USED_REGISTERS + /* Zero or more C statements that may conditionally modify two variables `fixed_regs' and `call_used_regs' (both of type `char []') after they have been initialized from the two preceding macros. @@ -649,7 +651,10 @@ extern enum m32r_sdata m32r_sdata; do \ { \ if (flag_pic) \ - fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ + { \ + fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ + call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ + } \ } \ while (0) #endif diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 242c2f76aa0..048e5a8a365 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -292,6 +292,7 @@ static void mips_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, static int symbolic_expression_p (rtx); static void mips_select_rtx_section (enum machine_mode, rtx, unsigned HOST_WIDE_INT); +static void mips_function_rodata_section (tree); static bool mips_in_small_data_p (tree); static int mips_fpr_return_fields (tree, tree *); static bool mips_return_in_msb (tree); @@ -722,6 +723,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = { #define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue #undef TARGET_ASM_SELECT_RTX_SECTION #define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section +#undef TARGET_ASM_FUNCTION_RODATA_SECTION +#define TARGET_ASM_FUNCTION_RODATA_SECTION mips_function_rodata_section #undef TARGET_SCHED_REORDER #define TARGET_SCHED_REORDER mips_sched_reorder @@ -6574,6 +6577,42 @@ mips_select_rtx_section (enum machine_mode mode, rtx x, } } +/* Implement TARGET_ASM_FUNCTION_RODATA_SECTION. + + The complication here is that, with the combination TARGET_ABICALLS + && !TARGET_GPWORD, jump tables will use absolute addresses, and should + therefore not be included in the read-only part of a DSO. Handle such + cases by selecting a normal data section instead of a read-only one. + The logic apes that in default_function_rodata_section. */ + +static void +mips_function_rodata_section (tree decl) +{ + if (!TARGET_ABICALLS || TARGET_GPWORD) + default_function_rodata_section (decl); + else if (decl && DECL_SECTION_NAME (decl)) + { + const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); + if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0) + { + char *rname = ASTRDUP (name); + rname[14] = 'd'; + named_section_real (rname, SECTION_LINKONCE | SECTION_WRITE, decl); + } + else if (flag_function_sections && flag_data_sections + && strncmp (name, ".text.", 6) == 0) + { + char *rname = ASTRDUP (name); + memcpy (rname + 1, "data", 4); + named_section_flags (rname, SECTION_WRITE); + } + else + data_section (); + } + else + data_section (); +} + /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to access DECL using %gp_rel(...)($gp). */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 70428ae78ed..3bcc72a6f90 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -2828,8 +2828,7 @@ beq\t%2,%.,1b\;\ "!TARGET_MIPS16" "<load>l\t%0,%2" [(set_attr "type" "load") - (set_attr "mode" "<MODE>") - (set_attr "hazard" "none")]) + (set_attr "mode" "<MODE>")]) (define_insn "mov_<load>r" [(set (match_operand:GPR 0 "register_operand" "=d") diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 5c5d8bf39f0..18fb21706a3 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -918,7 +918,8 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; }; We use a DImode register in the parallel for 5 to 7 byte structures so that there is only one element. This allows the object to be correctly padded. */ -#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) (TARGET_64BIT ? upward : downward) +#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \ + function_arg_padding ((MODE), (TYPE)) /* Do not expect to understand this without reading it several times. I'm tempted to try and simply it, but I worry about breaking something. */ diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 0eb29b1ea37..17866a9131e 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -23,6 +23,30 @@ [(UNSPEC_VSPLTISW 141) (UNSPEC_VSPLTISH 140) (UNSPEC_VSPLTISB 139) + (UNSPEC_VCMPBFP 50) + (UNSPEC_VCMPEQUB 51) + (UNSPEC_VCMPEQUH 52) + (UNSPEC_VCMPEQUW 53) + (UNSPEC_VCMPEQFP 54) + (UNSPEC_VCMPGEFP 55) + (UNSPEC_VCMPGTUB 56) + (UNSPEC_VCMPGTSB 57) + (UNSPEC_VCMPGTUH 58) + (UNSPEC_VCMPGTSH 59) + (UNSPEC_VCMPGTUW 60) + (UNSPEC_VCMPGTSW 61) + (UNSPEC_VCMPGTFP 62) + (UNSPEC_VSEL4SI 159) + (UNSPEC_VSEL4SF 160) + (UNSPEC_VSEL8HI 161) + (UNSPEC_VSEL16QI 162) + (UNSPEC_VCOND_V4SI 301) + (UNSPEC_VCOND_V4SF 302) + (UNSPEC_VCOND_V8HI 303) + (UNSPEC_VCOND_V16QI 304) + (UNSPEC_VCONDU_V4SI 305) + (UNSPEC_VCONDU_V8HI 306) + (UNSPEC_VCONDU_V16QI 307) ]) ;; Generic LVX load instruction. @@ -496,7 +520,8 @@ (define_insn "altivec_vcmpbfp" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v") - (match_operand:V4SF 2 "register_operand" "v")] 50))] + (match_operand:V4SF 2 "register_operand" "v")] + UNSPEC_VCMPBFP))] "TARGET_ALTIVEC" "vcmpbfp %0,%1,%2" [(set_attr "type" "veccmp")]) @@ -504,7 +529,8 @@ (define_insn "altivec_vcmpequb" [(set (match_operand:V16QI 0 "register_operand" "=v") (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] 51))] + (match_operand:V16QI 2 "register_operand" "v")] + UNSPEC_VCMPEQUB))] "TARGET_ALTIVEC" "vcmpequb %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -512,7 +538,8 @@ (define_insn "altivec_vcmpequh" [(set (match_operand:V8HI 0 "register_operand" "=v") (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] 52))] + (match_operand:V8HI 2 "register_operand" "v")] + UNSPEC_VCMPEQUH))] "TARGET_ALTIVEC" "vcmpequh %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -520,7 +547,8 @@ (define_insn "altivec_vcmpequw" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")] 53))] + (match_operand:V4SI 2 "register_operand" "v")] + UNSPEC_VCMPEQUW))] "TARGET_ALTIVEC" "vcmpequw %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -528,7 +556,8 @@ (define_insn "altivec_vcmpeqfp" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v") - (match_operand:V4SF 2 "register_operand" "v")] 54))] + (match_operand:V4SF 2 "register_operand" "v")] + UNSPEC_VCMPEQFP))] "TARGET_ALTIVEC" "vcmpeqfp %0,%1,%2" [(set_attr "type" "veccmp")]) @@ -536,7 +565,8 @@ (define_insn "altivec_vcmpgefp" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v") - (match_operand:V4SF 2 "register_operand" "v")] 55))] + (match_operand:V4SF 2 "register_operand" "v")] + UNSPEC_VCMPGEFP))] "TARGET_ALTIVEC" "vcmpgefp %0,%1,%2" [(set_attr "type" "veccmp")]) @@ -544,7 +574,8 @@ (define_insn "altivec_vcmpgtub" [(set (match_operand:V16QI 0 "register_operand" "=v") (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] 56))] + (match_operand:V16QI 2 "register_operand" "v")] + UNSPEC_VCMPGTUB))] "TARGET_ALTIVEC" "vcmpgtub %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -552,7 +583,8 @@ (define_insn "altivec_vcmpgtsb" [(set (match_operand:V16QI 0 "register_operand" "=v") (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] 57))] + (match_operand:V16QI 2 "register_operand" "v")] + UNSPEC_VCMPGTSB))] "TARGET_ALTIVEC" "vcmpgtsb %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -560,7 +592,8 @@ (define_insn "altivec_vcmpgtuh" [(set (match_operand:V8HI 0 "register_operand" "=v") (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] 58))] + (match_operand:V8HI 2 "register_operand" "v")] + UNSPEC_VCMPGTUH))] "TARGET_ALTIVEC" "vcmpgtuh %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -568,7 +601,8 @@ (define_insn "altivec_vcmpgtsh" [(set (match_operand:V8HI 0 "register_operand" "=v") (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] 59))] + (match_operand:V8HI 2 "register_operand" "v")] + UNSPEC_VCMPGTSH))] "TARGET_ALTIVEC" "vcmpgtsh %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -576,7 +610,8 @@ (define_insn "altivec_vcmpgtuw" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")] 60))] + (match_operand:V4SI 2 "register_operand" "v")] + UNSPEC_VCMPGTUW))] "TARGET_ALTIVEC" "vcmpgtuw %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -584,7 +619,8 @@ (define_insn "altivec_vcmpgtsw" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")] 61))] + (match_operand:V4SI 2 "register_operand" "v")] + UNSPEC_VCMPGTSW))] "TARGET_ALTIVEC" "vcmpgtsw %0,%1,%2" [(set_attr "type" "vecsimple")]) @@ -592,7 +628,8 @@ (define_insn "altivec_vcmpgtfp" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v") - (match_operand:V4SF 2 "register_operand" "v")] 62))] + (match_operand:V4SF 2 "register_operand" "v")] + UNSPEC_VCMPGTFP))] "TARGET_ALTIVEC" "vcmpgtfp %0,%1,%2" [(set_attr "type" "veccmp")]) @@ -1640,11 +1677,146 @@ "vrefp %0,%1" [(set_attr "type" "vecfloat")]) +(define_expand "vcondv4si" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V4SI 2 "register_operand" "v") + (match_operand:V4SI 3 "comparison_operator" "") + (match_operand:V4SI 4 "register_operand" "v") + (match_operand:V4SI 5 "register_operand" "v") + ] UNSPEC_VCOND_V4SI))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + +(define_expand "vconduv4si" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V4SI 2 "register_operand" "v") + (match_operand:V4SI 3 "comparison_operator" "") + (match_operand:V4SI 4 "register_operand" "v") + (match_operand:V4SI 5 "register_operand" "v") + ] UNSPEC_VCONDU_V4SI))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + +(define_expand "vcondv4sf" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V4SF 2 "register_operand" "v") + (match_operand:V4SF 3 "comparison_operator" "") + (match_operand:V4SF 4 "register_operand" "v") + (match_operand:V4SF 5 "register_operand" "v") + ] UNSPEC_VCOND_V4SF))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + +(define_expand "vcondv8hi" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V8HI 2 "register_operand" "v") + (match_operand:V8HI 3 "comparison_operator" "") + (match_operand:V8HI 4 "register_operand" "v") + (match_operand:V8HI 5 "register_operand" "v") + ] UNSPEC_VCOND_V8HI))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + +(define_expand "vconduv8hi" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V8HI 2 "register_operand" "v") + (match_operand:V8HI 3 "comparison_operator" "") + (match_operand:V8HI 4 "register_operand" "v") + (match_operand:V8HI 5 "register_operand" "v") + ] UNSPEC_VCONDU_V8HI))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + +(define_expand "vcondv16qi" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V16QI 2 "register_operand" "v") + (match_operand:V16QI 3 "comparison_operator" "") + (match_operand:V16QI 4 "register_operand" "v") + (match_operand:V16QI 5 "register_operand" "v") + ] UNSPEC_VCOND_V16QI))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + +(define_expand "vconduv16qi" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v") + (match_operand:V16QI 2 "register_operand" "v") + (match_operand:V16QI 3 "comparison_operator" "") + (match_operand:V16QI 4 "register_operand" "v") + (match_operand:V16QI 5 "register_operand" "v") + ] UNSPEC_VCONDU_V16QI))] + "TARGET_ALTIVEC" + " +{ + if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +} + ") + + (define_insn "altivec_vsel_4si" [(set (match_operand:V4SI 0 "register_operand" "=v") (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v") (match_operand:V4SI 2 "register_operand" "v") - (match_operand:V4SI 3 "register_operand" "v")] 159))] + (match_operand:V4SI 3 "register_operand" "v")] + UNSPEC_VSEL4SI))] "TARGET_ALTIVEC" "vsel %0,%1,%2,%3" [(set_attr "type" "vecperm")]) @@ -1653,7 +1825,8 @@ [(set (match_operand:V4SF 0 "register_operand" "=v") (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v") (match_operand:V4SF 2 "register_operand" "v") - (match_operand:V4SI 3 "register_operand" "v")] 160))] + (match_operand:V4SI 3 "register_operand" "v")] + UNSPEC_VSEL4SF))] "TARGET_ALTIVEC" "vsel %0,%1,%2,%3" [(set_attr "type" "vecperm")]) @@ -1662,7 +1835,8 @@ [(set (match_operand:V8HI 0 "register_operand" "=v") (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") (match_operand:V8HI 2 "register_operand" "v") - (match_operand:V8HI 3 "register_operand" "v")] 161))] + (match_operand:V8HI 3 "register_operand" "v")] + UNSPEC_VSEL8HI))] "TARGET_ALTIVEC" "vsel %0,%1,%2,%3" [(set_attr "type" "vecperm")]) @@ -1671,7 +1845,8 @@ [(set (match_operand:V16QI 0 "register_operand" "=v") (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") (match_operand:V16QI 2 "register_operand" "v") - (match_operand:V16QI 3 "register_operand" "v")] 162))] + (match_operand:V16QI 3 "register_operand" "v")] + UNSPEC_VSEL16QI))] "TARGET_ALTIVEC" "vsel %0,%1,%2,%3" [(set_attr "type" "vecperm")]) diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 32034dedab7..d3a3122ed5c 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -124,6 +124,7 @@ extern char * output_cbranch (rtx, const char *, int, rtx); extern char * output_e500_flip_eq_bit (rtx, rtx); extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx); +extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx); extern void output_toc (FILE *, rtx, int, enum machine_mode); extern void rs6000_initialize_trampoline (rtx, rtx, rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index be377ebf440..0d5c8b4d4b0 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -760,7 +760,15 @@ static tree rs6000_build_builtin_va_list (void); static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *); static bool rs6000_must_pass_in_stack (enum machine_mode, tree); static bool rs6000_vector_mode_supported_p (enum machine_mode); +static int get_vec_cmp_insn (enum rtx_code, enum machine_mode, + enum machine_mode); +static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx, + enum machine_mode); +static int get_vsel_insn (enum machine_mode); +static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx); + +const int INSN_NOT_AVAILABLE = -1; static enum machine_mode rs6000_eh_return_filter_mode (void); /* Hash table stuff for keeping track of TOC entries. */ @@ -11202,6 +11210,271 @@ output_e500_flip_eq_bit (rtx dst, rtx src) return string; } +/* Return insn index for the vector compare instruction for given CODE, + and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is + not available. */ + +static int +get_vec_cmp_insn (enum rtx_code code, + enum machine_mode dest_mode, + enum machine_mode op_mode) +{ + if (!TARGET_ALTIVEC) + return INSN_NOT_AVAILABLE; + + switch (code) + { + case EQ: + if (dest_mode == V16QImode && op_mode == V16QImode) + return UNSPEC_VCMPEQUB; + if (dest_mode == V8HImode && op_mode == V8HImode) + return UNSPEC_VCMPEQUH; + if (dest_mode == V4SImode && op_mode == V4SImode) + return UNSPEC_VCMPEQUW; + if (dest_mode == V4SImode && op_mode == V4SFmode) + return UNSPEC_VCMPEQFP; + break; + case GE: + if (dest_mode == V4SImode && op_mode == V4SFmode) + return UNSPEC_VCMPGEFP; + case GT: + if (dest_mode == V16QImode && op_mode == V16QImode) + return UNSPEC_VCMPGTSB; + if (dest_mode == V8HImode && op_mode == V8HImode) + return UNSPEC_VCMPGTSH; + if (dest_mode == V4SImode && op_mode == V4SImode) + return UNSPEC_VCMPGTSW; + if (dest_mode == V4SImode && op_mode == V4SFmode) + return UNSPEC_VCMPGTFP; + break; + case GTU: + if (dest_mode == V16QImode && op_mode == V16QImode) + return UNSPEC_VCMPGTUB; + if (dest_mode == V8HImode && op_mode == V8HImode) + return UNSPEC_VCMPGTUH; + if (dest_mode == V4SImode && op_mode == V4SImode) + return UNSPEC_VCMPGTUW; + break; + default: + break; + } + return INSN_NOT_AVAILABLE; +} + +/* Emit vector compare for operands OP0 and OP1 using code RCODE. + DMODE is expected destination mode. This is a recursive function. */ + +static rtx +rs6000_emit_vector_compare (enum rtx_code rcode, + rtx op0, rtx op1, + enum machine_mode dmode) +{ + int vec_cmp_insn; + rtx mask; + enum machine_mode dest_mode; + enum machine_mode op_mode = GET_MODE (op1); + +#ifdef ENABLE_CHECKING + if (!TARGET_ALTIVEC) + abort (); + + if (GET_MODE (op0) != GET_MODE (op1)) + abort (); +#endif + + /* Floating point vector compare instructions uses destination V4SImode. + Move destination to appropriate mode later. */ + if (dmode == V4SFmode) + dest_mode = V4SImode; + else + dest_mode = dmode; + + mask = gen_reg_rtx (dest_mode); + vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode); + + if (vec_cmp_insn == INSN_NOT_AVAILABLE) + { + bool swap_operands = false; + bool try_again = false; + switch (rcode) + { + case LT: + rcode = GT; + swap_operands = true; + try_again = true; + break; + case LTU: + rcode = GTU; + swap_operands = true; + try_again = true; + break; + case NE: + /* Treat A != B as ~(A==B). */ + { + enum insn_code nor_code; + rtx eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1, + dest_mode); + + nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code; + if (nor_code == CODE_FOR_nothing) + abort (); + emit_insn (GEN_FCN (nor_code) (mask, eq_rtx)); + + if (dmode != dest_mode) + { + rtx temp = gen_reg_rtx (dest_mode); + convert_move (temp, mask, 0); + return temp; + } + return mask; + } + break; + case GE: + case GEU: + case LE: + case LEU: + /* Try GT/GTU/LT/LTU OR EQ */ + { + rtx c_rtx, eq_rtx; + enum insn_code ior_code; + enum rtx_code new_code; + + if (rcode == GE) + new_code = GT; + else if (rcode == GEU) + new_code = GTU; + else if (rcode == LE) + new_code = LT; + else if (rcode == LEU) + new_code = LTU; + else + abort (); + + c_rtx = rs6000_emit_vector_compare (new_code, + op0, op1, dest_mode); + eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1, + dest_mode); + + ior_code = ior_optab->handlers[(int)dest_mode].insn_code; + if (ior_code == CODE_FOR_nothing) + abort (); + emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx)); + if (dmode != dest_mode) + { + rtx temp = gen_reg_rtx (dest_mode); + convert_move (temp, mask, 0); + return temp; + } + return mask; + } + break; + default: + abort (); + } + + if (try_again) + { + vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode); + if (vec_cmp_insn == INSN_NOT_AVAILABLE) + /* You only get two chances. */ + abort (); + } + + if (swap_operands) + { + rtx tmp; + tmp = op0; + op0 = op1; + op1 = tmp; + } + } + + emit_insn (gen_rtx_fmt_ee (SET, + VOIDmode, + mask, + gen_rtx_fmt_Ei (UNSPEC, dest_mode, + gen_rtvec (2, op0, op1), + vec_cmp_insn))); + if (dmode != dest_mode) + { + rtx temp = gen_reg_rtx (dest_mode); + convert_move (temp, mask, 0); + return temp; + } + return mask; +} + +/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if + valid insn doesn exist for given mode. */ + +static int +get_vsel_insn (enum machine_mode mode) +{ + switch (mode) + { + case V4SImode: + return UNSPEC_VSEL4SI; + break; + case V4SFmode: + return UNSPEC_VSEL4SF; + break; + case V8HImode: + return UNSPEC_VSEL8HI; + break; + case V16QImode: + return UNSPEC_VSEL16QI; + break; + default: + return INSN_NOT_AVAILABLE; + break; + } + return INSN_NOT_AVAILABLE; +} + +/* Emit vector select insn where DEST is destination using + operands OP1, OP2 and MASK. */ + +static void +rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask) +{ + rtx t, temp; + enum machine_mode dest_mode = GET_MODE (dest); + int vsel_insn_index = get_vsel_insn (GET_MODE (dest)); + + temp = gen_reg_rtx (dest_mode); + + t = gen_rtx_fmt_ee (SET, VOIDmode, temp, + gen_rtx_fmt_Ei (UNSPEC, dest_mode, + gen_rtvec (3, op1, op2, mask), + vsel_insn_index)); + emit_insn (t); + emit_move_insn (dest, temp); + return; +} + +/* Emit vector conditional expression. + DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands. + CC_OP0 and CC_OP1 are the two operands for the relation operation COND. */ + +int +rs6000_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2, + rtx cond, rtx cc_op0, rtx cc_op1) +{ + enum machine_mode dest_mode = GET_MODE (dest); + enum rtx_code rcode = GET_CODE (cond); + rtx mask; + + if (!TARGET_ALTIVEC) + return 0; + + /* Get the vector mask for the given relational operations. */ + mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode); + + rs6000_emit_vector_select (dest, op1, op2, mask); + + return 1; +} + /* Emit a conditional move: move TRUE_COND to DEST if OP of the operands of the last comparison is nonzero/true, FALSE_COND if it is zero/false. Return 0 if the hardware has no such operation. */ @@ -11216,6 +11489,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) enum machine_mode compare_mode = GET_MODE (op0); enum machine_mode result_mode = GET_MODE (dest); rtx temp; + bool is_against_zero; /* These modes should always match. */ if (GET_MODE (op1) != compare_mode @@ -11240,6 +11514,17 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) && GET_MODE_CLASS (compare_mode) == MODE_FLOAT) return 0; + is_against_zero = op1 == CONST0_RTX (compare_mode); + + /* A floating-point subtract might overflow, underflow, or produce + an inexact result, thus changing the floating-point flags, so it + can't be generated if we care about that. It's safe if one side + of the construct is zero, since then no subtract will be + generated. */ + if (GET_MODE_CLASS (compare_mode) == MODE_FLOAT + && flag_trapping_math && ! is_against_zero) + return 0; + /* Eliminate half of the comparisons by switching operands, this makes the remaining code simpler. */ if (code == UNLT || code == UNGT || code == UNORDERED || code == NE @@ -11272,14 +11557,18 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) || (! rtx_equal_p (op0, true_cond) && ! rtx_equal_p (op1, true_cond)))) return 0; + /* At this point we know we can use fsel. */ /* Reduce the comparison to a comparison against zero. */ - temp = gen_reg_rtx (compare_mode); - emit_insn (gen_rtx_SET (VOIDmode, temp, - gen_rtx_MINUS (compare_mode, op0, op1))); - op0 = temp; - op1 = CONST0_RTX (compare_mode); + if (! is_against_zero) + { + temp = gen_reg_rtx (compare_mode); + emit_insn (gen_rtx_SET (VOIDmode, temp, + gen_rtx_MINUS (compare_mode, op0, op1))); + op0 = temp; + op1 = CONST0_RTX (compare_mode); + } /* If we don't care about NaNs we can reduce some of the comparisons down to faster ones. */ diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 79a44a0ef57..59bef4137ea 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -1110,12 +1110,12 @@ extern int fixuplabelno; #ifdef HAVE_LD_PIE #define STARTFILE_LINUX_SPEC "\ -%{!shared: %{pg|p:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \ +%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \ %{mnewlib:ecrti.o%s;:crti.o%s} \ %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}" #else #define STARTFILE_LINUX_SPEC "\ -%{!shared: %{pg|p:gcrt1.o%s;:crt1.o%s}} \ +%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ %{mnewlib:ecrti.o%s;:crti.o%s} \ %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}" #endif diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 78b90a8b32c..4e88c1d0123 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -37,7 +37,6 @@ extern int const0_operand (rtx, enum machine_mode); extern int consttable_operand (rtx, enum machine_mode); extern int larl_operand (rtx, enum machine_mode); extern int s_operand (rtx, enum machine_mode); -extern int s_imm_operand (rtx, enum machine_mode); extern int shift_count_operand (rtx, enum machine_mode); extern int bras_sym_operand (rtx, enum machine_mode); extern int load_multiple_operation (rtx, enum machine_mode); @@ -88,6 +87,8 @@ extern rtx s390_emit_call (rtx, rtx, rtx, rtx); extern void s390_expand_logical_operator (enum rtx_code, enum machine_mode, rtx *); extern bool s390_logical_operator_ok_p (rtx *); +extern void s390_narrow_logical_operator (enum rtx_code, rtx *, rtx *); +extern bool s390_pool_operand (rtx); extern bool s390_output_addr_const_extra (FILE*, rtx); extern void print_operand_address (FILE *, rtx); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index c1414cf48f3..1d4d813458b 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -195,9 +195,9 @@ enum processor_flags s390_arch_flags; const char *s390_tune_string; /* for -mtune=<xxx> */ const char *s390_arch_string; /* for -march=<xxx> */ -/* String to specify backchain mode. */ -const char *s390_backchain_string = ""; /* "" no-backchain ,"1" backchain, - "2" kernel-backchain */ +/* String to specify backchain mode: + "" no-backchain, "1" backchain, "2" kernel-backchain. */ +const char *s390_backchain_string = TARGET_DEFAULT_BACKCHAIN; const char *s390_warn_framesize_string; const char *s390_warn_dynamicstack_string; @@ -279,7 +279,6 @@ static int s390_match_ccmode_set (rtx, enum machine_mode); static int s390_branch_condition_mask (rtx); static const char *s390_branch_condition_mnemonic (rtx, int); static int check_mode (rtx, enum machine_mode *); -static int general_s_operand (rtx, enum machine_mode, int); static int s390_short_displacement (rtx); static int s390_decompose_address (rtx, struct s390_address *); static rtx get_thread_pointer (void); @@ -1167,6 +1166,27 @@ s390_logical_operator_ok_p (rtx *operands) return true; } +/* Narrow logical operation CODE of memory operand MEMOP with immediate + operand IMMOP to switch from SS to SI type instructions. */ + +void +s390_narrow_logical_operator (enum rtx_code code, rtx *memop, rtx *immop) +{ + int def = code == AND ? -1 : 0; + HOST_WIDE_INT mask; + int part; + + gcc_assert (GET_CODE (*memop) == MEM); + gcc_assert (!MEM_VOLATILE_P (*memop)); + + mask = s390_extract_part (*immop, QImode, def); + part = s390_single_part (*immop, GET_MODE (*memop), QImode, def); + gcc_assert (part >= 0); + + *memop = adjust_address (*memop, QImode, part); + *immop = gen_int_mode (mask, QImode); +} + /* Change optimizations to be performed, depending on the optimization level. @@ -1423,15 +1443,12 @@ larl_operand (register rtx op, enum machine_mode mode) return 0; } -/* Helper routine to implement s_operand and s_imm_operand. +/* Return true if OP is a valid S-type operand. OP is the current operation. - MODE is the current operation mode. - ALLOW_IMMEDIATE specifies whether immediate operands should - be accepted or not. */ + MODE is the current operation mode. */ -static int -general_s_operand (register rtx op, enum machine_mode mode, - int allow_immediate) +int +s_operand (rtx op, enum machine_mode mode) { struct s390_address addr; @@ -1447,58 +1464,49 @@ general_s_operand (register rtx op, enum machine_mode mode, && GET_CODE (SUBREG_REG (op)) == MEM) op = SUBREG_REG (op); - switch (GET_CODE (op)) - { - /* Constants are OK as s-operand if ALLOW_IMMEDIATE - is true and we are still before reload. */ - case CONST_INT: - case CONST_DOUBLE: - if (!allow_immediate || reload_completed) - return 0; - return 1; - - /* Memory operands are OK unless they already use an - index register. */ - case MEM: - if (!s390_decompose_address (XEXP (op, 0), &addr)) - return 0; - if (addr.indx) - return 0; - /* Do not allow literal pool references unless ALLOW_IMMEDIATE - is true. This prevents compares between two literal pool - entries from being accepted. */ - if (!allow_immediate - && addr.base && REGNO (addr.base) == BASE_REGNUM) - return 0; - return 1; - - default: - break; - } + if (GET_CODE (op) != MEM) + return 0; + if (!s390_decompose_address (XEXP (op, 0), &addr)) + return 0; + if (addr.indx) + return 0; - return 0; + return 1; } -/* Return true if OP is a valid S-type operand. - OP is the current operation. - MODE is the current operation mode. */ +/* Return true if OP is a memory operand pointing to the + literal pool, or an immediate operand. */ -int -s_operand (register rtx op, enum machine_mode mode) +bool +s390_pool_operand (rtx op) { - return general_s_operand (op, mode, 0); -} + struct s390_address addr; -/* Return true if OP is a valid S-type operand or an immediate - operand that can be addressed as S-type operand by forcing - it into the literal pool. - OP is the current operation. - MODE is the current operation mode. */ + /* Just like memory_operand, allow (subreg (mem ...)) + after reload. */ + if (reload_completed + && GET_CODE (op) == SUBREG + && GET_CODE (SUBREG_REG (op)) == MEM) + op = SUBREG_REG (op); -int -s_imm_operand (register rtx op, enum machine_mode mode) -{ - return general_s_operand (op, mode, 1); + switch (GET_CODE (op)) + { + case CONST_INT: + case CONST_DOUBLE: + return true; + + case MEM: + if (!s390_decompose_address (XEXP (op, 0), &addr)) + return false; + if (addr.base && REG_P (addr.base) && REGNO (addr.base) == BASE_REGNUM) + return true; + if (addr.indx && REG_P (addr.indx) && REGNO (addr.indx) == BASE_REGNUM) + return true; + return false; + + default: + return false; + } } /* Return true if OP a valid shift count operand. @@ -1577,6 +1585,21 @@ s390_extra_constraint_str (rtx op, int c, const char * str) if (c != str[0]) abort (); + /* Check for offsettable variants of memory constraints. */ + if (c == 'A') + { + /* Only accept non-volatile MEMs. */ + if (!MEM_P (op) || MEM_VOLATILE_P (op)) + return 0; + + if ((reload_completed || reload_in_progress) + ? !offsettable_memref_p (op) + : !offsettable_nonstrict_memref_p (op)) + return 0; + + c = str[1]; + } + switch (c) { case 'Q': @@ -1671,7 +1694,7 @@ s390_const_ok_for_constraint_p (HOST_WIDE_INT value, { enum machine_mode mode, part_mode; int def; - unsigned char part; + int part, part_goal; if (c != str[0]) abort (); @@ -1695,7 +1718,10 @@ s390_const_ok_for_constraint_p (HOST_WIDE_INT value, return value == 2147483647; case 'N': - part = str[1] - '0'; + if (str[1] == 'x') + part_goal = -1; + else + part_goal = str[1] - '0'; switch (str[2]) { @@ -1722,7 +1748,10 @@ s390_const_ok_for_constraint_p (HOST_WIDE_INT value, if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (part_mode)) return 0; - if (s390_single_part (GEN_INT (value), mode, part_mode, def) != part) + part = s390_single_part (GEN_INT (value), mode, part_mode, def); + if (part < 0) + return 0; + if (part_goal != -1 && part_goal != part) return 0; break; @@ -6190,8 +6219,9 @@ s390_register_info (int live_regs[]) cfun_frame_layout.last_save_gpr = 6; /* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved. */ - for (i = 0; i < (TARGET_64BIT ? 4 : 2); i++) - cfun_set_fpr_bit (i); + if (TARGET_HARD_FLOAT) + for (i = 0; i < (TARGET_64BIT ? 4 : 2); i++) + cfun_set_fpr_bit (i); } if (!TARGET_64BIT) @@ -8374,6 +8404,12 @@ s390_conditional_register_usage (void) for (i = 18; i < 20; i++) call_used_regs[i] = call_really_used_regs[i] = 0; } + + if (TARGET_SOFT_FLOAT) + { + for (i = 16; i < 32; i++) + call_used_regs[i] = fixed_regs[i] = 1; + } } /* Corresponding function to eh_return expander. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 4d50395b67c..11b6d84ab6d 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -126,11 +126,13 @@ extern int target_flags; #define TARGET_IEEE_FLOAT 1 #ifdef DEFAULT_TARGET_64BIT -#define TARGET_DEFAULT 0x31 +#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_FLOAT) #else -#define TARGET_DEFAULT 0x1 +#define TARGET_DEFAULT MASK_HARD_FLOAT #endif +#define TARGET_DEFAULT_BACKCHAIN "" + #define TARGET_SWITCHES \ { { "hard-float", 1, N_("Use hardware fp")}, \ { "soft-float", -1, N_("Don't use hardware fp")}, \ @@ -542,13 +544,14 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; #define EXTRA_CONSTRAINT_STR(OP, C, STR) \ s390_extra_constraint_str ((OP), (C), (STR)) -#define EXTRA_MEMORY_CONSTRAINT(C, STR) \ - ((C) == 'Q' || (C) == 'R' || (C) == 'S' || (C) == 'T') -#define EXTRA_ADDRESS_CONSTRAINT(C, STR) \ +#define EXTRA_MEMORY_CONSTRAINT(C, STR) \ + ((C) == 'Q' || (C) == 'R' || (C) == 'S' || (C) == 'T' || (C) == 'A') +#define EXTRA_ADDRESS_CONSTRAINT(C, STR) \ ((C) == 'U' || (C) == 'W' || (C) == 'Y') -#define CONSTRAINT_LEN(C, STR) \ - ((C) == 'N' ? 5 : DEFAULT_CONSTRAINT_LEN ((C), (STR))) +#define CONSTRAINT_LEN(C, STR) \ + ((C) == 'N' ? 5 : \ + (C) == 'A' ? 2 : DEFAULT_CONSTRAINT_LEN ((C), (STR))) /* Stack layout and calling conventions. */ @@ -1015,7 +1018,6 @@ do { \ /* Define the codes that are matched by predicates in aux-output.c. */ #define PREDICATE_CODES \ {"s_operand", { SUBREG, MEM }}, \ - {"s_imm_operand", { CONST_INT, CONST_DOUBLE, SUBREG, MEM }}, \ {"shift_count_operand", { REG, SUBREG, PLUS, CONST_INT }}, \ {"bras_sym_operand",{ SYMBOL_REF, CONST }}, \ {"larl_operand", { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 5a649932329..7d59f0c0f7e 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -34,17 +34,21 @@ ;; (-524288..524287) for long displacement ;; M -- Constant integer with a value of 0x7fffffff. ;; N -- Multiple letter constraint followed by 4 parameter letters. -;; 0..9: number of the part counting from most to least significant -;; H,Q: mode of the part -;; D,S,H: mode of the containing operand -;; 0,F: value of the other parts (F - all bits set) +;; 0..9,x: number of the part counting from most to least significant +;; H,Q: mode of the part +;; D,S,H: mode of the containing operand +;; 0,F: value of the other parts (F - all bits set) ;; ;; The constraint matches if the specified part of a constant -;; has a value different from its other parts. +;; has a value different from its other parts. If the letter x +;; is specified instead of a part number, the constraint matches +;; if there is any single part with non-default value. ;; Q -- Memory reference without index register and with short displacement. ;; R -- Memory reference with index register and short displacement. ;; S -- Memory reference without index register but with long displacement. ;; T -- Memory reference with index register and long displacement. +;; A -- Multiple letter constraint followed by Q, R, S, or T: +;; Offsettable memory reference of type specified by second letter. ;; U -- Pointer with short displacement. ;; W -- Pointer with long displacement. ;; Y -- Shift count operand. @@ -517,6 +521,39 @@ [(set_attr "op_type" "RS,RSY")]) +; Compare (equality) instructions + +(define_insn "*cmpdi_cct" + [(set (reg 33) + (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,d,m,Q") + (match_operand:DI 1 "general_operand" "d,K,m,d,Q")))] + "s390_match_ccmode (insn, CCTmode) && TARGET_64BIT + && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))" + "@ + cgr\t%0,%1 + cghi\t%0,%c1 + cg\t%0,%1 + cg\t%1,%0 + clc\t%O0(8,%R0),%1" + [(set_attr "op_type" "RRE,RI,RXY,RXY,SS")]) + +(define_insn "*cmpsi_cct" + [(set (reg 33) + (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,d,R,T,Q") + (match_operand:SI 1 "general_operand" "d,K,R,T,d,d,Q")))] + "s390_match_ccmode (insn, CCTmode) + && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))" + "@ + cr\t%0,%1 + chi\t%0,%c1 + c\t%0,%1 + cy\t%0,%1 + c\t%1,%0 + cy\t%1,%0 + clc\t%O0(4,%R0),%1" + [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")]) + + ; Compare (signed) instructions (define_insn "*cmpdi_ccs_sign" @@ -569,7 +606,7 @@ [(set (reg 33) (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")) (match_operand:DI 0 "register_operand" "d,d")))] - "s390_match_ccmode(insn, CCURmode) && TARGET_64BIT" + "s390_match_ccmode (insn, CCURmode) && TARGET_64BIT" "@ clgfr\t%0,%1 clgf\t%0,%1" @@ -577,86 +614,56 @@ (define_insn "*cmpdi_ccu" [(set (reg 33) - (compare (match_operand:DI 0 "register_operand" "d,d") - (match_operand:DI 1 "general_operand" "d,m")))] - "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT" + (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,Q") + (match_operand:DI 1 "general_operand" "d,m,Q")))] + "s390_match_ccmode (insn, CCUmode) && TARGET_64BIT + && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))" "@ clgr\t%0,%1 - clg\t%0,%1" - [(set_attr "op_type" "RRE,RXY")]) + clg\t%0,%1 + clc\t%O0(8,%R0),%1" + [(set_attr "op_type" "RRE,RXY,SS")]) (define_insn "*cmpsi_ccu" [(set (reg 33) - (compare (match_operand:SI 0 "register_operand" "d,d,d") - (match_operand:SI 1 "general_operand" "d,R,T")))] - "s390_match_ccmode(insn, CCUmode)" + (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,Q") + (match_operand:SI 1 "general_operand" "d,R,T,Q")))] + "s390_match_ccmode (insn, CCUmode) + && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))" "@ clr\t%0,%1 cl\t%0,%1 - cly\t%0,%1" - [(set_attr "op_type" "RR,RX,RXY")]) + cly\t%0,%1 + clc\t%O0(4,%R0),%1" + [(set_attr "op_type" "RR,RX,RXY,SS")]) (define_insn "*cmphi_ccu" [(set (reg 33) - (compare (match_operand:HI 0 "register_operand" "d,d") - (match_operand:HI 1 "s_imm_operand" "Q,S")))] - "s390_match_ccmode(insn, CCUmode)" + (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q") + (match_operand:HI 1 "general_operand" "Q,S,Q")))] + "s390_match_ccmode (insn, CCUmode) + && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1])) + && !register_operand (operands[1], HImode)" "@ clm\t%0,3,%1 - clmy\t%0,3,%1" - [(set_attr "op_type" "RS,RSY")]) + clmy\t%0,3,%1 + clc\t%O0(2,%R0),%1" + [(set_attr "op_type" "RS,RSY,SS")]) (define_insn "*cmpqi_ccu" [(set (reg 33) - (compare (match_operand:QI 0 "register_operand" "d,d") - (match_operand:QI 1 "s_imm_operand" "Q,S")))] - "s390_match_ccmode(insn, CCUmode)" + (compare (match_operand:QI 0 "nonimmediate_operand" "d,d,Q,S,Q") + (match_operand:QI 1 "general_operand" "Q,S,n,n,Q")))] + "s390_match_ccmode (insn, CCUmode) + && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1])) + && !register_operand (operands[1], QImode)" "@ clm\t%0,1,%1 - clmy\t%0,1,%1" - [(set_attr "op_type" "RS,RSY")]) - -(define_insn "*cli" - [(set (reg 33) - (compare (match_operand:QI 0 "memory_operand" "Q,S") - (match_operand:QI 1 "immediate_operand" "n,n")))] - "s390_match_ccmode (insn, CCUmode)" - "@ + clmy\t%0,1,%1 cli\t%0,%b1 - cliy\t%0,%b1" - [(set_attr "op_type" "SI,SIY")]) - -(define_insn "*cmpdi_ccu_mem" - [(set (reg 33) - (compare (match_operand:DI 0 "s_operand" "Q") - (match_operand:DI 1 "s_imm_operand" "Q")))] - "s390_match_ccmode(insn, CCUmode)" - "clc\t%O0(8,%R0),%1" - [(set_attr "op_type" "SS")]) - -(define_insn "*cmpsi_ccu_mem" - [(set (reg 33) - (compare (match_operand:SI 0 "s_operand" "Q") - (match_operand:SI 1 "s_imm_operand" "Q")))] - "s390_match_ccmode(insn, CCUmode)" - "clc\t%O0(4,%R0),%1" - [(set_attr "op_type" "SS")]) - -(define_insn "*cmphi_ccu_mem" - [(set (reg 33) - (compare (match_operand:HI 0 "s_operand" "Q") - (match_operand:HI 1 "s_imm_operand" "Q")))] - "s390_match_ccmode(insn, CCUmode)" - "clc\t%O0(2,%R0),%1" - [(set_attr "op_type" "SS")]) - -(define_insn "*cmpqi_ccu_mem" - [(set (reg 33) - (compare (match_operand:QI 0 "s_operand" "Q") - (match_operand:QI 1 "s_imm_operand" "Q")))] - "s390_match_ccmode(insn, CCUmode)" - "clc\t%O0(1,%R0),%1" - [(set_attr "op_type" "SS")]) + cliy\t%0,%b1 + clc\t%O0(1,%R0),%1" + [(set_attr "op_type" "RS,RSY,SI,SIY,SS")]) ; DF instructions @@ -1264,7 +1271,7 @@ (define_insn "*movstricthi" [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d,d")) - (match_operand:HI 1 "s_imm_operand" "Q,S")) + (match_operand:HI 1 "memory_operand" "Q,S")) (clobber (reg:CC 33))] "" "@ @@ -5131,11 +5138,11 @@ [(set_attr "op_type" "RRE,RXY")]) (define_insn "*anddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,Q") + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,AQ,Q") (and:DI (match_operand:DI 1 "nonimmediate_operand" - "%d,o,0,0,0,0,0,0,0") + "%d,o,0,0,0,0,0,0,0,0") (match_operand:DI 2 "general_operand" - "M,M,N0HDF,N1HDF,N2HDF,N3HDF,d,m,Q"))) + "M,M,N0HDF,N1HDF,N2HDF,N3HDF,d,m,NxQDF,Q"))) (clobber (reg:CC 33))] "TARGET_64BIT && s390_logical_operator_ok_p (operands)" "@ @@ -5147,8 +5154,19 @@ nill\t%0,%j2 ngr\t%0,%2 ng\t%0,%2 + # nc\t%O0(8,%R0),%2" - [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RRE,RXY,SS")]) + [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RRE,RXY,SI,SS")]) + +(define_split + [(set (match_operand:DI 0 "s_operand" "") + (and:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);") (define_expand "anddi3" [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -5192,9 +5210,11 @@ [(set_attr "op_type" "RR,RX,RXY")]) (define_insn "*andsi3_zarch" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,Q") - (and:SI (match_operand:SI 1 "nonimmediate_operand" "%d,o,0,0,0,0,0,0") - (match_operand:SI 2 "general_operand" "M,M,N0HSF,N1HSF,d,R,T,Q"))) + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,AQ,Q") + (and:SI (match_operand:SI 1 "nonimmediate_operand" + "%d,o,0,0,0,0,0,0,0") + (match_operand:SI 2 "general_operand" + "M,M,N0HSF,N1HSF,d,R,T,NxQSF,Q"))) (clobber (reg:CC 33))] "TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ @@ -5205,20 +5225,32 @@ nr\t%0,%2 n\t%0,%2 ny\t%0,%2 + # nc\t%O0(4,%R0),%2" - [(set_attr "op_type" "RRE,RXE,RI,RI,RR,RX,RXY,SS")]) + [(set_attr "op_type" "RRE,RXE,RI,RI,RR,RX,RXY,SI,SS")]) (define_insn "*andsi3_esa" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,Q") - (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:SI 2 "general_operand" "d,R,Q"))) + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,AQ,Q") + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0") + (match_operand:SI 2 "general_operand" "d,R,NxQSF,Q"))) (clobber (reg:CC 33))] "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ nr\t%0,%2 n\t%0,%2 + # nc\t%O0(4,%R0),%2" - [(set_attr "op_type" "RR,RX,SS")]) + [(set_attr "op_type" "RR,RX,SI,SS")]) + +(define_split + [(set (match_operand:SI 0 "s_operand" "") + (and:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);") (define_expand "andsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "") @@ -5233,27 +5265,39 @@ ; (define_insn "*andhi3_zarch" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,Q") - (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:HI 2 "general_operand" "d,n,Q"))) + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,AQ,Q") + (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0,0") + (match_operand:HI 2 "general_operand" "d,n,NxQHF,Q"))) (clobber (reg:CC 33))] "TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ nr\t%0,%2 nill\t%0,%x2 + # nc\t%O0(2,%R0),%2" - [(set_attr "op_type" "RR,RI,SS")]) + [(set_attr "op_type" "RR,RI,SI,SS")]) (define_insn "*andhi3_esa" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,Q") - (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "d,Q"))) + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q") + (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:HI 2 "general_operand" "d,NxQHF,Q"))) (clobber (reg:CC 33))] "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ nr\t%0,%2 + # nc\t%O0(2,%R0),%2" - [(set_attr "op_type" "RR,SS")]) + [(set_attr "op_type" "RR,SI,SS")]) + +(define_split + [(set (match_operand:HI 0 "s_operand" "") + (and:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);") (define_expand "andhi3" [(set (match_operand:HI 0 "nonimmediate_operand" "") @@ -5336,10 +5380,10 @@ [(set_attr "op_type" "RRE,RXY")]) (define_insn "*iordi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,Q") - (ior:DI (match_operand:DI 1 "nonimmediate_operand" "0,0,0,0,0,0,0") + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,AQ,Q") + (ior:DI (match_operand:DI 1 "nonimmediate_operand" "0,0,0,0,0,0,0,0") (match_operand:DI 2 "general_operand" - "N0HD0,N1HD0,N2HD0,N3HD0,d,m,Q"))) + "N0HD0,N1HD0,N2HD0,N3HD0,d,m,NxQD0,Q"))) (clobber (reg:CC 33))] "TARGET_64BIT && s390_logical_operator_ok_p (operands)" "@ @@ -5349,8 +5393,19 @@ oill\t%0,%i2 ogr\t%0,%2 og\t%0,%2 + # oc\t%O0(8,%R0),%2" - [(set_attr "op_type" "RI,RI,RI,RI,RRE,RXY,SS")]) + [(set_attr "op_type" "RI,RI,RI,RI,RRE,RXY,SI,SS")]) + +(define_split + [(set (match_operand:DI 0 "s_operand" "") + (ior:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);") (define_expand "iordi3" [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -5392,9 +5447,9 @@ [(set_attr "op_type" "RR,RX,RXY")]) (define_insn "*iorsi3_zarch" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,Q") - (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0,0,0,0,0") - (match_operand:SI 2 "general_operand" "N0HS0,N1HS0,d,R,T,Q"))) + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,AQ,Q") + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0,0,0,0,0,0") + (match_operand:SI 2 "general_operand" "N0HS0,N1HS0,d,R,T,NxQS0,Q"))) (clobber (reg:CC 33))] "TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ @@ -5403,20 +5458,32 @@ or\t%0,%2 o\t%0,%2 oy\t%0,%2 + # oc\t%O0(4,%R0),%2" - [(set_attr "op_type" "RI,RI,RR,RX,RXY,SS")]) + [(set_attr "op_type" "RI,RI,RR,RX,RXY,SI,SS")]) (define_insn "*iorsi3_esa" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,Q") - (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0,0") - (match_operand:SI 2 "general_operand" "d,R,Q"))) + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,AQ,Q") + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0,0,0") + (match_operand:SI 2 "general_operand" "d,R,NxQS0,Q"))) (clobber (reg:CC 33))] "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ or\t%0,%2 o\t%0,%2 + # oc\t%O0(4,%R0),%2" - [(set_attr "op_type" "RR,RX,SS")]) + [(set_attr "op_type" "RR,RX,SI,SS")]) + +(define_split + [(set (match_operand:SI 0 "s_operand" "") + (ior:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);") (define_expand "iorsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "") @@ -5431,27 +5498,39 @@ ; (define_insn "*iorhi3_zarch" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,Q") - (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:HI 2 "general_operand" "d,n,Q"))) + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,AQ,Q") + (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0,0") + (match_operand:HI 2 "general_operand" "d,n,NxQH0,Q"))) (clobber (reg:CC 33))] "TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ or\t%0,%2 oill\t%0,%x2 + # oc\t%O0(2,%R0),%2" - [(set_attr "op_type" "RR,RI,SS")]) + [(set_attr "op_type" "RR,RI,SI,SS")]) (define_insn "*iorhi3_esa" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,Q") - (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "d,Q"))) + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q") + (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:HI 2 "general_operand" "d,NxQH0,Q"))) (clobber (reg:CC 33))] "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "@ or\t%0,%2 + # oc\t%O0(2,%R0),%2" - [(set_attr "op_type" "RR,SS")]) + [(set_attr "op_type" "RR,SI,SS")]) + +(define_split + [(set (match_operand:HI 0 "s_operand" "") + (ior:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);") (define_expand "iorhi3" [(set (match_operand:HI 0 "nonimmediate_operand" "") @@ -5534,16 +5613,27 @@ [(set_attr "op_type" "RRE,RXY")]) (define_insn "*xordi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,Q") - (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:DI 2 "general_operand" "d,m,Q"))) + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,AQ,Q") + (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0") + (match_operand:DI 2 "general_operand" "d,m,NxQD0,Q"))) (clobber (reg:CC 33))] "TARGET_64BIT && s390_logical_operator_ok_p (operands)" "@ xgr\t%0,%2 xg\t%0,%2 + # xc\t%O0(8,%R0),%2" - [(set_attr "op_type" "RRE,RXY,SS")]) + [(set_attr "op_type" "RRE,RXY,SI,SS")]) + +(define_split + [(set (match_operand:DI 0 "s_operand" "") + (xor:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);") (define_expand "xordi3" [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -5585,17 +5675,28 @@ [(set_attr "op_type" "RR,RX,RXY")]) (define_insn "*xorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,Q") - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0") - (match_operand:SI 2 "general_operand" "d,R,T,Q"))) + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,AQ,Q") + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0") + (match_operand:SI 2 "general_operand" "d,R,T,NxQS0,Q"))) (clobber (reg:CC 33))] "s390_logical_operator_ok_p (operands)" "@ xr\t%0,%2 x\t%0,%2 xy\t%0,%2 + # xc\t%O0(4,%R0),%2" - [(set_attr "op_type" "RR,RX,RXY,SS")]) + [(set_attr "op_type" "RR,RX,RXY,SI,SS")]) + +(define_split + [(set (match_operand:SI 0 "s_operand" "") + (xor:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);") (define_expand "xorsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "") @@ -5610,15 +5711,26 @@ ; (define_insn "*xorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,Q") - (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "d,Q"))) + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q") + (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:HI 2 "general_operand" "d,NxQH0,Q"))) (clobber (reg:CC 33))] "s390_logical_operator_ok_p (operands)" "@ xr\t%0,%2 + # xc\t%O0(2,%R0),%2" - [(set_attr "op_type" "RR,SS")]) + [(set_attr "op_type" "RR,SI,SS")]) + +(define_split + [(set (match_operand:HI 0 "s_operand" "") + (xor:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" ""))) + (clobber (reg:CC 33))] + "reload_completed" + [(parallel + [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1))) + (clobber (reg:CC 33))])] + "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);") (define_expand "xorhi3" [(set (match_operand:HI 0 "nonimmediate_operand" "") diff --git a/gcc/config/s390/tpf.h b/gcc/config/s390/tpf.h index 8ba13e25412..e6a016a7771 100644 --- a/gcc/config/s390/tpf.h +++ b/gcc/config/s390/tpf.h @@ -54,9 +54,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #undef STACK_POINTER_OFFSET #define STACK_POINTER_OFFSET 448 -/* When building for TPF, set a generic default target that is 64 bits. */ +/* When building for TPF, set a generic default target that is 64 bits. + Also, enable TPF profiling support and the standard backchain by default. */ #undef TARGET_DEFAULT -#define TARGET_DEFAULT 0xb3 +#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_FLOAT \ + | MASK_TPF_PROFILING) +#undef TARGET_DEFAULT_BACKCHAIN +#define TARGET_DEFAULT_BACKCHAIN "1" /* Exception handling. */ diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 349d981ccc9..d88e159bd1f 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -9413,7 +9413,7 @@ int sh_dwarf_calling_convention (tree func) { if (sh_attr_renesas_p (func)) - return DW_CC_renesas_sh; + return DW_CC_GNU_renesas_sh; return DW_CC_normal; } @@ -10095,7 +10095,7 @@ sh_init_cumulative_args (CUMULATIVE_ARGS * pcum, pcum->prototype_p = FALSE; if (mode != VOIDmode) { - pcum->call_cookie = + pcum->call_cookie = CALL_COOKIE_RET_TRAMP (TARGET_SHCOMPACT && GET_MODE_SIZE (mode) > 4 && BASE_RETURN_VALUE_REG (mode) == FIRST_RET_REG); diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 5adcac22664..dd9f216b587 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -6869,8 +6869,8 @@ (define_insn "tls_global_dynamic" [(set (match_operand:SI 0 "register_operand" "=&z") - (call (unspec:SI [(match_operand:SI 1 "" "")] - UNSPEC_TLSGD) + (call (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] + UNSPEC_TLSGD)) (const_int 0))) (use (reg:PSI FPSCR_REG)) (use (reg:SI PIC_REG)) @@ -6898,8 +6898,8 @@ mov.l\\t1f,r4\\n\\ (define_insn "tls_local_dynamic" [(set (match_operand:SI 0 "register_operand" "=&z") - (call (unspec:SI [(match_operand:SI 1 "" "")] - UNSPEC_TLSLDM) + (call (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] + UNSPEC_TLSLDM)) (const_int 0))) (use (reg:PSI FPSCR_REG)) (use (reg:SI PIC_REG)) @@ -10951,17 +10951,45 @@ mov.l\\t1f,r0\\n\\ "byterev %1, %0" [(set_attr "type" "arith_media")]) -(define_insn "prefetch" +(define_insn "prefetch_media" [(prefetch (match_operand:QI 0 "address_operand" "p") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] - "TARGET_SHMEDIA || TARGET_HARD_SH4" + "TARGET_SHMEDIA" "* { - if (TARGET_HARD_SH4) - return \"pref @%0\"; operands[0] = gen_rtx_MEM (QImode, operands[0]); output_asm_insn (\"ld%M0.b %m0,r63\", operands); return \"\"; }" [(set_attr "type" "other")]) + +(define_insn "prefetch_i4" + [(prefetch (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "const_int_operand" "n"))] + "TARGET_HARD_SH4" + "* +{ + return \"pref @%0\"; +}" + [(set_attr "type" "other")]) + +(define_expand "prefetch" + [(prefetch (match_operand:QI 0 "address_operand" "p") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "const_int_operand" "n"))] + "TARGET_SHMEDIA || TARGET_HARD_SH4" + " +{ + if (TARGET_HARD_SH4 && ! register_operand (operands[0], SImode)) + { + rtx reg = gen_reg_rtx (SImode); + emit_move_insn (reg, operands[0]); + operands[0] = reg; + } + + emit_insn ((TARGET_SHMEDIA ? gen_prefetch_media : gen_prefetch_i4) + (operands[0], operands[1], operands[2])); + DONE; +}") diff --git a/gcc/config/sh/symbian.c b/gcc/config/sh/symbian.c index e4b0d2bc225..02b95f5970d 100644 --- a/gcc/config/sh/symbian.c +++ b/gcc/config/sh/symbian.c @@ -559,8 +559,7 @@ symbian_possibly_export_base_class (tree base_class) tree methods; int len; - if (! (TYPE_POLYMORPHIC_P (base_class) - || TYPE_USES_VIRTUAL_BASECLASSES (base_class))) + if (! (TYPE_CONTAINS_VPTR_P (base_class))) return; methods = CLASSTYPE_METHOD_VEC (base_class); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index aa1fa0905b1..3f75954e6cc 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -1547,23 +1547,7 @@ input_operand (rtx op, enum machine_mode mode) /* Check for valid MEM forms. */ if (GET_CODE (op) == MEM) - { - rtx inside = XEXP (op, 0); - - if (GET_CODE (inside) == LO_SUM) - { - /* We can't allow these because all of the splits - (eventually as they trickle down into DFmode - splits) require offsettable memory references. */ - if (! TARGET_V9 - && GET_MODE (op) == TFmode) - return 0; - - return (register_operand (XEXP (inside, 0), Pmode) - && CONSTANT_P (XEXP (inside, 1))); - } - return memory_address_p (mode, inside); - } + return memory_address_p (mode, XEXP (op, 0)); return 0; } @@ -3516,15 +3500,14 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict) else if ((REG_P (rs1) || GET_CODE (rs1) == SUBREG) && (REG_P (rs2) || GET_CODE (rs2) == SUBREG)) { - /* We prohibit REG + REG for TFmode when there are no instructions - which accept REG+REG instructions. We do this because REG+REG - is not an offsetable address. If we get the situation in reload + /* We prohibit REG + REG for TFmode when there are no quad move insns + and we consequently need to split. We do this because REG+REG + is not an offsettable address. If we get the situation in reload where source and destination of a movtf pattern are both MEMs with REG+REG address, then only one of them gets converted to an - offsetable address. */ + offsettable address. */ if (mode == TFmode - && !(TARGET_FPU && TARGET_ARCH64 && TARGET_V9 - && TARGET_HARD_QUAD)) + && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD)) return 0; /* We prohibit REG + REG on ARCH32 if not optimizing for @@ -3557,10 +3540,25 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict) if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1)) return 0; - /* We can't allow TFmode, because an offset greater than or equal to the - alignment (8) may cause the LO_SUM to overflow if !v9. */ - if (mode == TFmode && !TARGET_V9) - return 0; + if (USE_AS_OFFSETABLE_LO10) + { + /* We can't allow TFmode, because an offset greater than or equal to + the alignment (8) may cause the LO_SUM to overflow if !v9. */ + if (mode == TFmode && ! TARGET_V9) + return 0; + } + else + { + /* We prohibit LO_SUM for TFmode when there are no quad move insns + and we consequently need to split. We do this because LO_SUM + is not an offsettable address. If we get the situation in reload + where source and destination of a movtf pattern are both MEMs with + LO_SUM address, then only one of them gets converted to an + offsettable address. */ + if (mode == TFmode + && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD)) + return 0; + } } else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr)) return 1; @@ -6024,7 +6022,7 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) bool indirect; tree ptrtype = build_pointer_type (type); - if (pass_by_reference (NULL, TYPE_MODE (type), type, 0)) + if (pass_by_reference (NULL, TYPE_MODE (type), type, false)) { indirect = true; size = rsize = UNITS_PER_WORD; @@ -6044,7 +6042,7 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) align = 2 * UNITS_PER_WORD; /* SPARC-V9 ABI states that structures up to 16 bytes in size - are given whole slots as needed. */ + are left-justified in their slots. */ if (AGGREGATE_TYPE_P (type)) { if (size == 0) @@ -6074,7 +6072,7 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) if (indirect) { addr = fold_convert (build_pointer_type (ptrtype), addr); - addr = build_fold_indirect_ref (addr); + addr = build_va_arg_indirect_ref (addr); } /* If the address isn't aligned properly for the type, we may need to copy to a temporary. @@ -6103,7 +6101,7 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr); gimplify_and_add (incr, post_p); - return build_fold_indirect_ref (addr); + return build_va_arg_indirect_ref (addr); } /* Return the string to output an unconditional branch to LABEL, which is @@ -8543,7 +8541,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, { /* We will emit a regular sibcall below, so we need to instruct output_sibcall that we are in a leaf function. */ - sparc_leaf_function_p = 1; + sparc_leaf_function_p = current_function_uses_only_leaf_regs = 1; /* This will cause final.c to invoke leaf_renumber_regs so we must behave as if we were in a not-yet-leafified function. */ @@ -8553,7 +8551,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, { /* We will emit the sibcall manually below, so we will need to manually spill non-leaf registers. */ - sparc_leaf_function_p = 0; + sparc_leaf_function_p = current_function_uses_only_leaf_regs = 0; /* We really are in a leaf function. */ int_arg_first = SPARC_OUTGOING_INT_ARG_FIRST; |