Submitted By: William Harrington (kb0iic at cross-lfs dot org) Date: 30-03-2014 Initial Package Version: 4.8.2 Origin: Upstream Upstream Status: Applied Description: This is a branch update for gcc-4.8.2, and should be rechecked periodically. Includes PR tree-optimization/54094 This patch was made from Revision # 208943. diff -Naur gcc-4.8.2.orig/boehm-gc/include/private/gcconfig.h gcc-4.8.2/boehm-gc/include/private/gcconfig.h --- gcc-4.8.2.orig/boehm-gc/include/private/gcconfig.h 2013-03-06 15:08:58.000000000 +0000 +++ gcc-4.8.2/boehm-gc/include/private/gcconfig.h 2014-03-30 20:21:40.550931139 +0000 @@ -837,7 +837,15 @@ # define NO_PTHREAD_TRYLOCK # endif # ifdef FREEBSD +# if defined(__powerpc64__) +# define ALIGNMENT 8 +# define CPP_WORDSZ 64 +# ifndef HBLKSIZE +# define HBLKSIZE 4096 +# endif +# else # define ALIGNMENT 4 +# endif # define OS_TYPE "FREEBSD" # ifndef GC_FREEBSD_THREADS # define MPROTECT_VDB diff -Naur gcc-4.8.2.orig/contrib/gcc_update gcc-4.8.2/contrib/gcc_update --- gcc-4.8.2.orig/contrib/gcc_update 2012-11-14 11:09:00.000000000 +0000 +++ gcc-4.8.2/contrib/gcc_update 2014-03-30 20:21:40.550931139 +0000 @@ -382,7 +382,7 @@ fi revision=`$GCC_SVN info | awk '/Revision:/ { print $2 }'` - branch=`$GCC_SVN info | sed -ne "/URL:/ { + branch=`$GCC_SVN info | sed -ne "/^URL:/ { s,.*/trunk,trunk, s,.*/branches/,, s,.*/tags/,, diff -Naur gcc-4.8.2.orig/gcc/ChangeLog gcc-4.8.2/gcc/ChangeLog --- gcc-4.8.2.orig/gcc/ChangeLog 2013-10-16 07:20:05.000000000 +0000 +++ gcc-4.8.2/gcc/ChangeLog 2014-03-30 20:29:59.087238765 +0000 @@ -696,6 +696,15 @@ top. Promote lra_assert to gcc_assert. (reload_pseudo_compare_func): Check regs first for reload pseudos. +2013-07-13 Tobias Grosser + + PR tree-optimization/54094 + * graphite-clast-to-gimple.c (translate_clast_for_loop): Derive the + scheduling dimension for the parallelism check from the polyhedral + information in the AST. + * graphite-dependences.c (carries_deps): Do not assume the schedule is + in 2D + 1 form. + 2013-07-11 Georg-Johann Lay Backport from 2013-07-19 trunk r201051. diff -Naur gcc-4.8.2.orig/gcc/DATESTAMP gcc-4.8.2/gcc/DATESTAMP --- gcc-4.8.2.orig/gcc/DATESTAMP 2013-10-16 00:16:34.000000000 +0000 +++ gcc-4.8.2/gcc/DATESTAMP 2014-03-30 20:21:40.650928664 +0000 @@ -1 +1 @@ -20131016 +20140330 diff -Naur gcc-4.8.2.orig/gcc/Makefile.in gcc-4.8.2/gcc/Makefile.in --- gcc-4.8.2.orig/gcc/Makefile.in 2013-07-08 09:14:34.000000000 +0000 +++ gcc-4.8.2/gcc/Makefile.in 2014-03-30 20:21:40.694263438 +0000 @@ -1827,7 +1827,7 @@ "$(MULTILIB_EXCLUSIONS)" \ "$(MULTILIB_OSDIRNAMES)" \ "$(MULTILIB_REQUIRED)" \ - "$(MULTIARCH_DIRNAME)" \ + "$(if $(MULTILIB_OSDIRNAMES),,$(MULTIARCH_DIRNAME))" \ "$(MULTILIB_REUSE)" \ "@enable_multilib@" \ > tmp-mlib.h; \ @@ -2256,7 +2256,7 @@ $(FUNCTION_H) $(TM_H) coretypes.h \ $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \ $(FLAGS_H) $(HASHTAB_H) pointer-set.h \ - $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H) + $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H) tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_P_H) $(EXPR_H) $(DIAGNOSTIC_H) \ toplev.h $(FUNCTION_H) $(TM_H) coretypes.h \ @@ -3037,7 +3037,7 @@ $(TM_H) coretypes.h $(GIMPLE_H) \ $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) \ $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H) \ - $(GIMPLE_PRETTY_PRINT_H) langhooks.h + $(GIMPLE_PRETTY_PRINT_H) langhooks.h $(OPTABS_H) tree-complex.o : tree-complex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \ $(TM_H) $(FLAGS_H) $(TREE_FLOW_H) $(GIMPLE_H) \ tree-iterator.h $(TREE_PASS_H) tree-ssa-propagate.h @@ -3276,12 +3276,12 @@ $(TM_H) $(RTL_H) $(REGS_H) insn-config.h insn-codes.h $(DF_H) \ $(RECOG_H) output.h addresses.h $(REGS_H) hard-reg-set.h $(FLAGS_H) \ $(FUNCTION_H) $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) \ - ira.h rtl-error.h $(LRA_INT_H) + ira.h rtl-error.h $(LRA_INT_H) $(OPTABS_H) lra-eliminations.o : lra-eliminations.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \ $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \ $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) ira.h \ - rtl-error.h $(LRA_INT_H) + rtl-error.h $(LRA_INT_H) $(OPTABS_H) lra-lives.o : lra-lives.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \ $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \ diff -Naur gcc-4.8.2.orig/gcc/ada/back_end.ads gcc-4.8.2/gcc/ada/back_end.ads --- gcc-4.8.2.orig/gcc/ada/back_end.ads 2011-08-04 08:33:14.000000000 +0000 +++ gcc-4.8.2/gcc/ada/back_end.ads 2014-03-30 20:21:40.554264291 +0000 @@ -55,6 +55,7 @@ Complex : Boolean; -- True iff type has real and imaginary parts Count : Natural; -- Number of elements in vector, 0 otherwise Float_Rep : Float_Rep_Kind; -- Representation used for fpt type + Precision : Positive; -- Precision of representation in bits Size : Positive; -- Size of representation in bits Alignment : Natural); -- Required alignment in bits pragma Convention (C, Register_Type_Proc); diff -Naur gcc-4.8.2.orig/gcc/ada/cstand.adb gcc-4.8.2/gcc/ada/cstand.adb --- gcc-4.8.2.orig/gcc/ada/cstand.adb 2012-10-01 09:41:22.000000000 +0000 +++ gcc-4.8.2/gcc/ada/cstand.adb 2014-03-30 20:21:40.554264291 +0000 @@ -151,6 +151,7 @@ Complex : Boolean; -- True iff type has real and imaginary parts Count : Natural; -- Number of elements in vector, 0 otherwise Float_Rep : Float_Rep_Kind; -- Representation used for fpt type + Precision : Positive; -- Precision of representation in bits Size : Positive; -- Size of representation in bits Alignment : Natural); -- Required alignment in bits pragma Convention (C, Register_Float_Type); @@ -2014,6 +2015,7 @@ Complex : Boolean; Count : Natural; Float_Rep : Float_Rep_Kind; + Precision : Positive; Size : Positive; Alignment : Natural) is @@ -2063,13 +2065,24 @@ else Write_Str ("mod 2**"); - Write_Int (Int (Size / Positive'Max (1, Count))); + Write_Int (Int (Precision / Positive'Max (1, Count))); Write_Line (";"); end if; - Write_Str ("for " & T & "'Size use "); - Write_Int (Int (Size)); - Write_Line (";"); + if Precision = Size then + Write_Str ("for " & T (1 .. Last) & "'Size use "); + Write_Int (Int (Size)); + Write_Line (";"); + + else + Write_Str ("for " & T (1 .. Last) & "'Value_Size use "); + Write_Int (Int (Precision)); + Write_Line (";"); + + Write_Str ("for " & T (1 .. Last) & "'Object_Size use "); + Write_Int (Int (Size)); + Write_Line (";"); + end if; Write_Str ("for " & T & "'Alignment use "); Write_Int (Int (Alignment / 8)); @@ -2092,15 +2105,13 @@ if Digs > 0 and then not Complex and then Count = 0 then declare Ent : constant Entity_Id := New_Standard_Entity; - Esize : constant Pos := Pos ((Size + Alignment - 1) - / Alignment * Alignment); begin Set_Defining_Identifier (New_Node (N_Full_Type_Declaration, Stloc), Ent); Make_Name (Ent, T (1 .. Last)); Set_Scope (Ent, Standard_Standard); - Build_Float_Type (Ent, Esize, Float_Rep, Pos (Digs)); - Set_RM_Size (Ent, UI_From_Int (Int (Size))); + Build_Float_Type (Ent, Int (Size), Float_Rep, Pos (Digs)); + Set_RM_Size (Ent, UI_From_Int (Int (Precision))); Set_Alignment (Ent, UI_From_Int (Int (Alignment / 8))); if No (Back_End_Float_Types) then diff -Naur gcc-4.8.2.orig/gcc/ada/gcc-interface/Make-lang.in gcc-4.8.2/gcc/ada/gcc-interface/Make-lang.in --- gcc-4.8.2.orig/gcc/ada/gcc-interface/Make-lang.in 2013-02-06 11:13:07.000000000 +0000 +++ gcc-4.8.2/gcc/ada/gcc-interface/Make-lang.in 2014-03-30 20:21:40.557597408 +0000 @@ -625,7 +625,7 @@ ada/doctools/xgnatugn$(build_exeext): ada/xgnatugn.adb -$(MKDIR) ada/doctools $(CP) $^ ada/doctools - cd ada/doctools && $(GNATMAKE) -q xgnatugn + cd ada/doctools && gnatmake -q xgnatugn # Note that doc/gnat_ugn.texi and doc/projects.texi do not depend on # xgnatugn being built so we can distribute a pregenerated doc/gnat_ugn.info diff -Naur gcc-4.8.2.orig/gcc/ada/gcc-interface/Makefile.in gcc-4.8.2/gcc/ada/gcc-interface/Makefile.in --- gcc-4.8.2.orig/gcc/ada/gcc-interface/Makefile.in 2013-02-06 11:19:08.000000000 +0000 +++ gcc-4.8.2/gcc/ada/gcc-interface/Makefile.in 2014-03-30 20:21:40.554264291 +0000 @@ -2397,7 +2397,7 @@ "GNATLINK=$(GNATLINK)" \ "GNATBIND=$(GNATBIND)" -GCC_LINK=$(CC) $(GCC_LINK_FLAGS) $(ADA_INCLUDES) +GCC_LINK=$(CC) $(GCC_LINK_FLAGS) $(ADA_INCLUDES) $(LDFLAGS) # Build directory for the tools. Let's copy the target-dependent # sources using the same mechanism as for gnatlib. The other sources are @@ -2519,12 +2519,10 @@ # Likewise for the tools ../../gnatmake$(exeext): $(P) b_gnatm.o link.o targext.o $(GNATMAKE_OBJS) - $(GCC_LINK) $(ALL_CFLAGS) $(LDFLAGS) -o $@ b_gnatm.o $(GNATMAKE_OBJS) \ - $(TOOLS_LIBS) + +$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatm.o $(GNATMAKE_OBJS) $(TOOLS_LIBS) ../../gnatlink$(exeext): $(P) b_gnatl.o link.o targext.o $(GNATLINK_OBJS) - $(GCC_LINK) $(ALL_CFLAGS) $(LDFLAGS) -o $@ b_gnatl.o $(GNATLINK_OBJS) \ - $(TOOLS_LIBS) + +$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatl.o $(GNATLINK_OBJS) $(TOOLS_LIBS) ../stamp-gnatlib-$(RTSDIR): @if [ ! -f stamp-gnatlib-$(RTSDIR) ] ; \ diff -Naur gcc-4.8.2.orig/gcc/ada/gcc-interface/cuintp.c gcc-4.8.2/gcc/ada/gcc-interface/cuintp.c --- gcc-4.8.2.orig/gcc/ada/gcc-interface/cuintp.c 2012-05-10 15:05:39.000000000 +0000 +++ gcc-4.8.2/gcc/ada/gcc-interface/cuintp.c 2014-03-30 20:21:40.554264291 +0000 @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2012, Free Software Foundation, Inc. * + * Copyright (C) 1992-2014, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -59,8 +59,8 @@ static tree build_cst_from_int (tree type, HOST_WIDE_INT low) { - if (TREE_CODE (type) == REAL_TYPE) - return convert (type, build_int_cst (NULL_TREE, low)); + if (SCALAR_FLOAT_TYPE_P (type)) + return convert (type, build_int_cst (gnat_type_for_size (32, 0), low)); else return build_int_cst_type (type, low); } @@ -99,19 +99,12 @@ gcc_assert (Length > 0); /* The computations we perform below always require a type at least as - large as an integer not to overflow. REAL types are always fine, but + large as an integer not to overflow. FP types are always fine, but INTEGER or ENUMERAL types we are handed may be too short. We use a base integer type node for the computations in this case and will - convert the final result back to the incoming type later on. - The base integer precision must be superior than 16. */ - - if (TREE_CODE (comp_type) != REAL_TYPE - && TYPE_PRECISION (comp_type) - < TYPE_PRECISION (long_integer_type_node)) - { - comp_type = long_integer_type_node; - gcc_assert (TYPE_PRECISION (comp_type) > 16); - } + convert the final result back to the incoming type later on. */ + if (!SCALAR_FLOAT_TYPE_P (comp_type) && TYPE_PRECISION (comp_type) < 32) + comp_type = gnat_type_for_size (32, 0); gnu_base = build_cst_from_int (comp_type, Base); diff -Naur gcc-4.8.2.orig/gcc/ada/gcc-interface/gigi.h gcc-4.8.2/gcc/ada/gcc-interface/gigi.h --- gcc-4.8.2.orig/gcc/ada/gcc-interface/gigi.h 2013-06-13 07:51:32.000000000 +0000 +++ gcc-4.8.2/gcc/ada/gcc-interface/gigi.h 2014-03-30 20:21:40.554264291 +0000 @@ -1014,7 +1014,7 @@ /* This function is called by the front-end to enumerate all the supported modes for the machine, as well as some predefined C types. */ extern void enumerate_modes (void (*f) (const char *, int, int, int, int, int, - int)); + int, int)); #ifdef __cplusplus } diff -Naur gcc-4.8.2.orig/gcc/ada/gcc-interface/misc.c gcc-4.8.2/gcc/ada/gcc-interface/misc.c --- gcc-4.8.2.orig/gcc/ada/gcc-interface/misc.c 2013-01-02 10:45:00.000000000 +0000 +++ gcc-4.8.2/gcc/ada/gcc-interface/misc.c 2014-03-30 20:21:40.557597408 +0000 @@ -648,7 +648,7 @@ /* This function is called by the front-end to enumerate all the supported modes for the machine, as well as some predefined C types. F is a function which is called back with the parameters as listed below, first a string, - then six ints. The name is any arbitrary null-terminated string and has + then seven ints. The name is any arbitrary null-terminated string and has no particular significance, except for the case of predefined C types, where it should be the name of the C type. For integer types, only signed types should be listed, unsigned versions are assumed. The order of types should @@ -664,11 +664,12 @@ COMPLEX_P nonzero is this represents a complex mode COUNT count of number of items, nonzero for vector mode FLOAT_REP Float_Rep_Kind for FP, otherwise undefined - SIZE number of bits used to store data + PRECISION number of bits used to store data + SIZE number of bits occupied by the mode ALIGN number of bits to which mode is aligned. */ void -enumerate_modes (void (*f) (const char *, int, int, int, int, int, int)) +enumerate_modes (void (*f) (const char *, int, int, int, int, int, int, int)) { const tree c_types[] = { float_type_node, double_type_node, long_double_type_node }; @@ -742,28 +743,26 @@ /* First register any C types for this mode that the front end may need to know about, unless the mode should be skipped. */ - - if (!skip_p) + if (!skip_p && !vector_p) for (nameloop = 0; nameloop < ARRAY_SIZE (c_types); nameloop++) { - tree typ = c_types[nameloop]; - const char *nam = c_names[nameloop]; + tree type = c_types[nameloop]; + const char *name = c_names[nameloop]; - if (TYPE_MODE (typ) == i) + if (TYPE_MODE (type) == i) { - f (nam, digs, complex_p, - vector_p ? GET_MODE_NUNITS (i) : 0, float_rep, - TYPE_PRECISION (typ), TYPE_ALIGN (typ)); + f (name, digs, complex_p, 0, float_rep, TYPE_PRECISION (type), + TREE_INT_CST_LOW (TYPE_SIZE (type)), TYPE_ALIGN (type)); skip_p = true; } } /* If no predefined C types were found, register the mode itself. */ - if (!skip_p) f (GET_MODE_NAME (i), digs, complex_p, vector_p ? GET_MODE_NUNITS (i) : 0, float_rep, - GET_MODE_PRECISION (i), GET_MODE_ALIGNMENT (i)); + GET_MODE_PRECISION (i), GET_MODE_BITSIZE (i), + GET_MODE_ALIGNMENT (i)); } } diff -Naur gcc-4.8.2.orig/gcc/ada/gcc-interface/utils.c gcc-4.8.2/gcc/ada/gcc-interface/utils.c --- gcc-4.8.2.orig/gcc/ada/gcc-interface/utils.c 2013-06-13 07:51:32.000000000 +0000 +++ gcc-4.8.2/gcc/ada/gcc-interface/utils.c 2014-03-30 20:21:40.557597408 +0000 @@ -232,6 +232,7 @@ static tree split_plus (tree, tree *); static tree float_type_for_precision (int, enum machine_mode); static tree convert_to_fat_pointer (tree, tree); +static unsigned int scale_by_factor_of (tree, unsigned int); static bool potential_alignment_gap (tree, tree, tree); static void process_attributes (tree, struct attrib *); @@ -532,6 +533,22 @@ free_binding_level = level; } +/* Set the context of TYPE and its parallel types (if any) to CONTEXT. */ + +static void +gnat_set_type_context (tree type, tree context) +{ + tree decl = TYPE_STUB_DECL (type); + + TYPE_CONTEXT (type) = context; + + while (decl && DECL_PARALLEL_TYPE (decl)) + { + TYPE_CONTEXT (DECL_PARALLEL_TYPE (decl)) = context; + decl = TYPE_STUB_DECL (DECL_PARALLEL_TYPE (decl)); + } +} + /* Record DECL as belonging to the current lexical scope and use GNAT_NODE for location information and flag propagation. */ @@ -613,7 +630,7 @@ if (TREE_CODE (t) == POINTER_TYPE) TYPE_NEXT_PTR_TO (t) = tt; TYPE_NAME (tt) = DECL_NAME (decl); - TYPE_CONTEXT (tt) = DECL_CONTEXT (decl); + gnat_set_type_context (tt, DECL_CONTEXT (decl)); TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (t); DECL_ORIGINAL_TYPE (decl) = tt; } @@ -623,7 +640,7 @@ /* We need a variant for the placeholder machinery to work. */ tree tt = build_variant_type_copy (t); TYPE_NAME (tt) = decl; - TYPE_CONTEXT (tt) = DECL_CONTEXT (decl); + gnat_set_type_context (tt, DECL_CONTEXT (decl)); TREE_USED (tt) = TREE_USED (t); TREE_TYPE (decl) = tt; if (DECL_ORIGINAL_TYPE (TYPE_NAME (t))) @@ -645,7 +662,7 @@ if (!(TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)) { TYPE_NAME (t) = decl; - TYPE_CONTEXT (t) = DECL_CONTEXT (decl); + gnat_set_type_context (t, DECL_CONTEXT (decl)); } } } @@ -1692,93 +1709,74 @@ TYPE_SIZE_UNIT (new_record_type) = size_int (TYPE_ALIGN (record_type) / BITS_PER_UNIT); - /* Now scan all the fields, replacing each field with a new - field corresponding to the new encoding. */ + /* Now scan all the fields, replacing each field with a new field + corresponding to the new encoding. */ for (old_field = TYPE_FIELDS (record_type); old_field; old_field = DECL_CHAIN (old_field)) { tree field_type = TREE_TYPE (old_field); tree field_name = DECL_NAME (old_field); - tree new_field; tree curpos = bit_position (old_field); + tree pos, new_field; bool var = false; unsigned int align = 0; - tree pos; - - /* See how the position was modified from the last position. - There are two basic cases we support: a value was added - to the last position or the last position was rounded to - a boundary and they something was added. Check for the - first case first. If not, see if there is any evidence - of rounding. If so, round the last position and try - again. + /* We're going to do some pattern matching below so remove as many + conversions as possible. */ + curpos = remove_conversions (curpos, true); - If this is a union, the position can be taken as zero. */ + /* See how the position was modified from the last position. - /* Some computations depend on the shape of the position expression, - so strip conversions to make sure it's exposed. */ - curpos = remove_conversions (curpos, true); + There are two basic cases we support: a value was added + to the last position or the last position was rounded to + a boundary and they something was added. Check for the + first case first. If not, see if there is any evidence + of rounding. If so, round the last position and retry. + If this is a union, the position can be taken as zero. */ if (TREE_CODE (new_record_type) == UNION_TYPE) - pos = bitsize_zero_node, align = 0; + pos = bitsize_zero_node; else pos = compute_related_constant (curpos, last_pos); - if (!pos && TREE_CODE (curpos) == MULT_EXPR + if (!pos + && TREE_CODE (curpos) == MULT_EXPR && host_integerp (TREE_OPERAND (curpos, 1), 1)) { tree offset = TREE_OPERAND (curpos, 0); align = tree_low_cst (TREE_OPERAND (curpos, 1), 1); - - /* An offset which is a bitwise AND with a mask increases the - alignment according to the number of trailing zeros. */ - offset = remove_conversions (offset, true); - if (TREE_CODE (offset) == BIT_AND_EXPR - && TREE_CODE (TREE_OPERAND (offset, 1)) == INTEGER_CST) - { - unsigned HOST_WIDE_INT mask - = TREE_INT_CST_LOW (TREE_OPERAND (offset, 1)); - unsigned int i; - - for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++) - { - if (mask & 1) - break; - mask >>= 1; - align *= 2; - } - } - - pos = compute_related_constant (curpos, - round_up (last_pos, align)); + align = scale_by_factor_of (offset, align); + last_pos = round_up (last_pos, align); + pos = compute_related_constant (curpos, last_pos); } - else if (!pos && TREE_CODE (curpos) == PLUS_EXPR - && TREE_CODE (TREE_OPERAND (curpos, 1)) == INTEGER_CST + else if (!pos + && TREE_CODE (curpos) == PLUS_EXPR + && host_integerp (TREE_OPERAND (curpos, 1), 1) && TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR - && host_integerp (TREE_OPERAND - (TREE_OPERAND (curpos, 0), 1), - 1)) + && host_integerp + (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1)) { + tree offset = TREE_OPERAND (TREE_OPERAND (curpos, 0), 0); + unsigned HOST_WIDE_INT addend + = tree_low_cst (TREE_OPERAND (curpos, 1), 1); align - = tree_low_cst - (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1); - pos = compute_related_constant (curpos, - round_up (last_pos, align)); + = tree_low_cst (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1); + align = scale_by_factor_of (offset, align); + align = MIN (align, addend & -addend); + last_pos = round_up (last_pos, align); + pos = compute_related_constant (curpos, last_pos); } - else if (potential_alignment_gap (prev_old_field, old_field, - pos)) + else if (potential_alignment_gap (prev_old_field, old_field, pos)) { align = TYPE_ALIGN (field_type); - pos = compute_related_constant (curpos, - round_up (last_pos, align)); + last_pos = round_up (last_pos, align); + pos = compute_related_constant (curpos, last_pos); } /* If we can't compute a position, set it to zero. - ??? We really should abort here, but it's too much work - to get this correct for all cases. */ - + ??? We really should abort here, but it's too much work + to get this correct for all cases. */ if (!pos) pos = bitsize_zero_node; @@ -2553,6 +2551,32 @@ return false; } +/* Return VALUE scaled by the biggest power-of-2 factor of EXPR. */ + +static unsigned int +scale_by_factor_of (tree expr, unsigned int value) +{ + expr = remove_conversions (expr, true); + + /* An expression which is a bitwise AND with a mask has a power-of-2 factor + corresponding to the number of trailing zeros of the mask. */ + if (TREE_CODE (expr) == BIT_AND_EXPR + && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST) + { + unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)); + unsigned int i = 0; + + while ((mask & 1) == 0 && i < HOST_BITS_PER_WIDE_INT) + { + mask >>= 1; + value *= 2; + i++; + } + } + + return value; +} + /* Given two consecutive field decls PREV_FIELD and CURR_FIELD, return true unless we can prove these 2 fields are laid out in such a way that no gap exist between the end of PREV_FIELD and the beginning of CURR_FIELD. OFFSET diff -Naur gcc-4.8.2.orig/gcc/ada/indepsw-darwin.adb gcc-4.8.2/gcc/ada/indepsw-darwin.adb --- gcc-4.8.2.orig/gcc/ada/indepsw-darwin.adb 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/ada/indepsw-darwin.adb 2014-03-30 20:21:40.560930524 +0000 @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- I N D E P S W -- +-- -- +-- B o d y -- +-- (Darwin version) -- +-- -- +-- Copyright (C) 2013, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This is the Darwin version + +package body Indepsw is + + Map_Switch : aliased constant String := "-Wl,-map,"; + + ------------- + -- Convert -- + ------------- + + procedure Convert + (Switch : Switch_Kind; + Argument : String; + To : out String_List_Access) + is + begin + case Switch is + when Map_File => + To := new Argument_List'(1 => new String'(Map_Switch & Argument)); + end case; + end Convert; + + ------------------ + -- Is_Supported -- + ------------------ + + function Is_Supported (Switch : Switch_Kind) return Boolean is + begin + case Switch is + when Map_File => + return True; + end case; + end Is_Supported; + +end Indepsw; diff -Naur gcc-4.8.2.orig/gcc/alias.c gcc-4.8.2/gcc/alias.c --- gcc-4.8.2.orig/gcc/alias.c 2013-03-05 09:40:38.000000000 +0000 +++ gcc-4.8.2/gcc/alias.c 2014-03-30 20:21:40.560930524 +0000 @@ -156,7 +156,9 @@ static alias_set_entry get_alias_set_entry (alias_set_type); static bool nonoverlapping_component_refs_p (const_rtx, const_rtx); static tree decl_for_component_ref (tree); -static int write_dependence_p (const_rtx, const_rtx, int); +static int write_dependence_p (const_rtx, + const_rtx, enum machine_mode, rtx, + bool, bool, bool); static void memory_modified_1 (rtx, const_rtx, void *); @@ -2558,15 +2560,24 @@ } /* Returns nonzero if a write to X might alias a previous read from - (or, if WRITEP is nonzero, a write to) MEM. */ + (or, if WRITEP is true, a write to) MEM. + If X_CANONCALIZED is true, then X_ADDR is the canonicalized address of X, + and X_MODE the mode for that access. + If MEM_CANONICALIZED is true, MEM is canonicalized. */ static int -write_dependence_p (const_rtx mem, const_rtx x, int writep) +write_dependence_p (const_rtx mem, + const_rtx x, enum machine_mode x_mode, rtx x_addr, + bool mem_canonicalized, bool x_canonicalized, bool writep) { - rtx x_addr, mem_addr; + rtx mem_addr; rtx base; int ret; + gcc_checking_assert (x_canonicalized + ? (x_addr != NULL_RTX && x_mode != VOIDmode) + : (x_addr == NULL_RTX && x_mode == VOIDmode)); + if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) return 1; @@ -2590,17 +2601,21 @@ if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x)) return 1; - x_addr = XEXP (x, 0); mem_addr = XEXP (mem, 0); - if (!((GET_CODE (x_addr) == VALUE - && GET_CODE (mem_addr) != VALUE - && reg_mentioned_p (x_addr, mem_addr)) - || (GET_CODE (x_addr) != VALUE - && GET_CODE (mem_addr) == VALUE - && reg_mentioned_p (mem_addr, x_addr)))) + if (!x_addr) { - x_addr = get_addr (x_addr); - mem_addr = get_addr (mem_addr); + x_addr = XEXP (x, 0); + if (!((GET_CODE (x_addr) == VALUE + && GET_CODE (mem_addr) != VALUE + && reg_mentioned_p (x_addr, mem_addr)) + || (GET_CODE (x_addr) != VALUE + && GET_CODE (mem_addr) == VALUE + && reg_mentioned_p (mem_addr, x_addr)))) + { + x_addr = get_addr (x_addr); + if (!mem_canonicalized) + mem_addr = get_addr (mem_addr); + } } if (! writep) @@ -2616,11 +2631,16 @@ GET_MODE (mem))) return 0; - x_addr = canon_rtx (x_addr); - mem_addr = canon_rtx (mem_addr); + if (!x_canonicalized) + { + x_addr = canon_rtx (x_addr); + x_mode = GET_MODE (x); + } + if (!mem_canonicalized) + mem_addr = canon_rtx (mem_addr); if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr, - SIZE_FOR_MODE (x), x_addr, 0)) != -1) + GET_MODE_SIZE (x_mode), x_addr, 0)) != -1) return ret; if (nonoverlapping_memrefs_p (x, mem, false)) @@ -2634,7 +2654,23 @@ int anti_dependence (const_rtx mem, const_rtx x) { - return write_dependence_p (mem, x, /*writep=*/0); + return write_dependence_p (mem, x, VOIDmode, NULL_RTX, + /*mem_canonicalized=*/false, + /*x_canonicalized*/false, /*writep=*/false); +} + +/* Likewise, but we already have a canonicalized MEM, and X_ADDR for X. + Also, consider X in X_MODE (which might be from an enclosing + STRICT_LOW_PART / ZERO_EXTRACT). + If MEM_CANONICALIZED is true, MEM is canonicalized. */ + +int +canon_anti_dependence (const_rtx mem, bool mem_canonicalized, + const_rtx x, enum machine_mode x_mode, rtx x_addr) +{ + return write_dependence_p (mem, x, x_mode, x_addr, + mem_canonicalized, /*x_canonicalized=*/true, + /*writep=*/false); } /* Output dependence: X is written after store in MEM takes place. */ @@ -2642,7 +2678,9 @@ int output_dependence (const_rtx mem, const_rtx x) { - return write_dependence_p (mem, x, /*writep=*/1); + return write_dependence_p (mem, x, VOIDmode, NULL_RTX, + /*mem_canonicalized=*/false, + /*x_canonicalized*/false, /*writep=*/true); } @@ -2871,16 +2909,13 @@ /* Wipe the reg_seen array clean. */ bitmap_clear (reg_seen); - /* Mark all hard registers which may contain an address. - The stack, frame and argument pointers may contain an address. - An argument register which can hold a Pmode value may contain - an address even if it is not in BASE_REGS. - - The address expression is VOIDmode for an argument and - Pmode for other registers. */ - - memcpy (new_reg_base_value, static_reg_base_value, - FIRST_PSEUDO_REGISTER * sizeof (rtx)); + /* Initialize the alias information for this pass. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (static_reg_base_value[i]) + { + new_reg_base_value[i] = static_reg_base_value[i]; + bitmap_set_bit (reg_seen, i); + } /* Walk the insns adding values to the new_reg_base_value array. */ for (i = 0; i < rpo_cnt; i++) diff -Naur gcc-4.8.2.orig/gcc/bb-reorder.c gcc-4.8.2/gcc/bb-reorder.c --- gcc-4.8.2.orig/gcc/bb-reorder.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/bb-reorder.c 2014-03-30 20:21:40.560930524 +0000 @@ -1685,9 +1685,8 @@ edge e; edge_iterator ei; - /* Find EDGE_CAN_FALLTHRU edge. */ FOR_EACH_EDGE (e, ei, cur_bb->succs) - if (e->flags & EDGE_CAN_FALLTHRU) + if (e->flags & EDGE_FALLTHRU) { fall_thru = e; break; diff -Naur gcc-4.8.2.orig/gcc/builtins.c gcc-4.8.2/gcc/builtins.c --- gcc-4.8.2.orig/gcc/builtins.c 2013-05-03 08:55:08.000000000 +0000 +++ gcc-4.8.2/gcc/builtins.c 2014-03-30 20:21:40.560930524 +0000 @@ -180,7 +180,6 @@ static tree fold_builtin_strpbrk (location_t, tree, tree, tree); static tree fold_builtin_strstr (location_t, tree, tree, tree); static tree fold_builtin_strrchr (location_t, tree, tree, tree); -static tree fold_builtin_strcat (location_t, tree, tree); static tree fold_builtin_strncat (location_t, tree, tree, tree); static tree fold_builtin_strspn (location_t, tree, tree); static tree fold_builtin_strcspn (location_t, tree, tree); @@ -1958,6 +1957,7 @@ tree fndecl = get_callee_fndecl (exp); enum machine_mode mode; bool errno_set = false; + bool try_widening = false; tree arg; if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) @@ -1969,6 +1969,7 @@ { CASE_FLT_FN (BUILT_IN_SQRT): errno_set = ! tree_expr_nonnegative_p (arg); + try_widening = true; builtin_optab = sqrt_optab; break; CASE_FLT_FN (BUILT_IN_EXP): @@ -2025,8 +2026,10 @@ if (! flag_errno_math || ! HONOR_NANS (mode)) errno_set = false; - /* Before working hard, check whether the instruction is available. */ - if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing + /* Before working hard, check whether the instruction is available, but try + to widen the mode for specific operations. */ + if ((optab_handler (builtin_optab, mode) != CODE_FOR_nothing + || (try_widening && !excess_precision_type (TREE_TYPE (exp)))) && (!errno_set || !optimize_insn_for_size_p ())) { rtx result = gen_reg_rtx (mode); @@ -5347,7 +5350,7 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp, rtx target) { - rtx expect, desired, mem, oldval; + rtx expect, desired, mem, oldval, label; enum memmodel success, failure; tree weak; bool is_weak; @@ -5385,14 +5388,26 @@ if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0) is_weak = true; - oldval = expect; - if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target), - &oldval, mem, oldval, desired, + if (target == const0_rtx) + target = NULL; + + /* Lest the rtl backend create a race condition with an imporoper store + to memory, always create a new pseudo for OLDVAL. */ + oldval = NULL; + + if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired, is_weak, success, failure)) return NULL_RTX; - if (oldval != expect) - emit_move_insn (expect, oldval); + /* Conditionally store back to EXPECT, lest we create a race condition + with an improper store to memory. */ + /* ??? With a rearrangement of atomics at the gimple level, we can handle + the normal case where EXPECT is totally private, i.e. a register. At + which point the store can be unconditional. */ + label = gen_label_rtx (); + emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL, VOIDmode, 1, label); + emit_move_insn (expect, oldval); + emit_label (label); return target; } @@ -10766,7 +10781,7 @@ return fold_builtin_strstr (loc, arg0, arg1, type); case BUILT_IN_STRCAT: - return fold_builtin_strcat (loc, arg0, arg1); + return fold_builtin_strcat (loc, arg0, arg1, NULL_TREE); case BUILT_IN_STRSPN: return fold_builtin_strspn (loc, arg0, arg1); @@ -11809,8 +11824,9 @@ COMPOUND_EXPR in the chain will contain the tree for the simplified form of the builtin function call. */ -static tree -fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src) +tree +fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src, + tree len) { if (!validate_arg (dst, POINTER_TYPE) || !validate_arg (src, POINTER_TYPE)) @@ -11828,22 +11844,17 @@ /* See if we can store by pieces into (dst + strlen(dst)). */ tree newdst, call; tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN); - tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY); + tree memcpy_fn = builtin_decl_implicit (BUILT_IN_MEMCPY); - if (!strlen_fn || !strcpy_fn) + if (!strlen_fn || !memcpy_fn) return NULL_TREE; - /* If we don't have a movstr we don't want to emit an strcpy - call. We have to do that if the length of the source string - isn't computable (in that case we can use memcpy probably - later expanding to a sequence of mov instructions). If we - have movstr instructions we can emit strcpy calls. */ - if (!HAVE_movstr) - { - tree len = c_strlen (src, 1); - if (! len || TREE_SIDE_EFFECTS (len)) - return NULL_TREE; - } + /* If the length of the source string isn't computable don't + split strcat into strlen and memcpy. */ + if (! len) + len = c_strlen (src, 1); + if (! len || TREE_SIDE_EFFECTS (len)) + return NULL_TREE; /* Stabilize the argument list. */ dst = builtin_save_expr (dst); @@ -11855,7 +11866,11 @@ newdst = fold_build_pointer_plus_loc (loc, dst, newdst); newdst = builtin_save_expr (newdst); - call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src); + len = fold_convert_loc (loc, size_type_node, len); + len = size_binop_loc (loc, PLUS_EXPR, len, + build_int_cst (size_type_node, 1)); + + call = build_call_expr_loc (loc, memcpy_fn, 3, newdst, src, len); return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst); } return NULL_TREE; diff -Naur gcc-4.8.2.orig/gcc/c/c-decl.c gcc-4.8.2/gcc/c/c-decl.c --- gcc-4.8.2.orig/gcc/c/c-decl.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/c/c-decl.c 2014-03-30 20:21:40.564263645 +0000 @@ -4632,7 +4632,9 @@ { int failure = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl), true); - gcc_assert (!failure); + /* If complete_array_type returns 3, it means that the + initial value of the compound literal is empty. Allow it. */ + gcc_assert (failure == 0 || failure == 3); type = TREE_TYPE (decl); TREE_TYPE (DECL_INITIAL (decl)) = type; diff -Naur gcc-4.8.2.orig/gcc/c/c-typeck.c gcc-4.8.2/gcc/c/c-typeck.c --- gcc-4.8.2.orig/gcc/c/c-typeck.c 2013-01-24 16:59:44.000000000 +0000 +++ gcc-4.8.2/gcc/c/c-typeck.c 2014-03-30 20:21:40.564263645 +0000 @@ -3629,7 +3629,8 @@ /* Report invalid types. */ if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE - && typecode != INTEGER_TYPE && typecode != REAL_TYPE) + && typecode != INTEGER_TYPE && typecode != REAL_TYPE + && typecode != VECTOR_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) error_at (location, "wrong type argument to increment"); @@ -3694,7 +3695,9 @@ } else { - inc = integer_one_node; + inc = (TREE_CODE (argtype) == VECTOR_TYPE + ? build_one_cst (argtype) + : integer_one_node); inc = convert (argtype, inc); } @@ -4331,8 +4334,10 @@ { if (int_operands) { - op1 = remove_c_maybe_const_expr (op1); - op2 = remove_c_maybe_const_expr (op2); + /* Use c_fully_fold here, since C_MAYBE_CONST_EXPR might be + nested inside of the expression. */ + op1 = c_fully_fold (op1, false, NULL); + op2 = c_fully_fold (op2, false, NULL); } ret = build3 (COND_EXPR, result_type, ifexp, op1, op2); if (int_operands) @@ -10618,7 +10623,8 @@ "%qE has invalid type for %", t); remove = true; } - else if (FLOAT_TYPE_P (TREE_TYPE (t))) + else if (FLOAT_TYPE_P (TREE_TYPE (t)) + || TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) { enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c); const char *r_name = NULL; @@ -10628,8 +10634,14 @@ case PLUS_EXPR: case MULT_EXPR: case MINUS_EXPR: + break; case MIN_EXPR: + if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) + r_name = "min"; + break; case MAX_EXPR: + if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) + r_name = "max"; break; case BIT_AND_EXPR: r_name = "&"; @@ -10641,10 +10653,12 @@ r_name = "|"; break; case TRUTH_ANDIF_EXPR: - r_name = "&&"; + if (FLOAT_TYPE_P (TREE_TYPE (t))) + r_name = "&&"; break; case TRUTH_ORIF_EXPR: - r_name = "||"; + if (FLOAT_TYPE_P (TREE_TYPE (t))) + r_name = "||"; break; default: gcc_unreachable (); diff -Naur gcc-4.8.2.orig/gcc/c-family/c-common.c gcc-4.8.2/gcc/c-family/c-common.c --- gcc-4.8.2.orig/gcc/c-family/c-common.c 2013-05-14 20:52:27.000000000 +0000 +++ gcc-4.8.2/gcc/c-family/c-common.c 2014-03-30 20:21:40.564263645 +0000 @@ -2894,7 +2894,7 @@ } if (!found) { - *end = copy ? add : new_tlist (NULL, add->expr, add->writer); + *end = copy ? new_tlist (NULL, add->expr, add->writer) : add; end = &(*end)->next; *end = 0; } @@ -3052,7 +3052,7 @@ verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_list2, NULL_TREE); warn_for_collisions (tmp_list2); merge_tlist (pbefore_sp, tmp_before, 0); - merge_tlist (pbefore_sp, tmp_list2, 1); + merge_tlist (pbefore_sp, tmp_list2, 0); tmp_list3 = tmp_nosp = 0; verify_tree (TREE_OPERAND (x, 1), &tmp_list3, &tmp_nosp, NULL_TREE); @@ -3156,12 +3156,7 @@ warn_for_collisions (tmp_nosp); tmp_list3 = 0; - while (tmp_nosp) - { - struct tlist *t = tmp_nosp; - tmp_nosp = t->next; - merge_tlist (&tmp_list3, t, 0); - } + merge_tlist (&tmp_list3, tmp_nosp, 0); t->cache_before_sp = tmp_before; t->cache_after_sp = tmp_list3; } @@ -5511,13 +5506,13 @@ uint8_type_node = TREE_TYPE (identifier_global_value (c_get_ident (UINT8_TYPE))); if (UINT16_TYPE) - c_uint16_type_node = + c_uint16_type_node = uint16_type_node = TREE_TYPE (identifier_global_value (c_get_ident (UINT16_TYPE))); if (UINT32_TYPE) - c_uint32_type_node = + c_uint32_type_node = uint32_type_node = TREE_TYPE (identifier_global_value (c_get_ident (UINT32_TYPE))); if (UINT64_TYPE) - c_uint64_type_node = + c_uint64_type_node = uint64_type_node = TREE_TYPE (identifier_global_value (c_get_ident (UINT64_TYPE))); if (INT_LEAST8_TYPE) int_least8_type_node = @@ -6917,6 +6912,10 @@ } arg = TREE_VALUE (args); + if (TREE_CODE (arg) == IDENTIFIER_NODE) + goto invalid; + if (arg == error_mark_node) + return DEFAULT_INIT_PRIORITY; arg = default_conversion (arg); if (!host_integerp (arg, /*pos=*/0) || !INTEGRAL_TYPE_P (TREE_TYPE (arg))) @@ -9763,6 +9762,11 @@ "invalid type argument of %<->%> (have %qT)", type); break; + case RO_ARROW_STAR: + error_at (loc, + "invalid type argument of %<->*%> (have %qT)", + type); + break; case RO_IMPLICIT_CONVERSION: error_at (loc, "invalid type argument of implicit conversion (have %qT)", diff -Naur gcc-4.8.2.orig/gcc/cfgcleanup.c gcc-4.8.2/gcc/cfgcleanup.c --- gcc-4.8.2.orig/gcc/cfgcleanup.c 2013-09-10 11:48:30.000000000 +0000 +++ gcc-4.8.2/gcc/cfgcleanup.c 2014-03-30 20:21:40.567596893 +0000 @@ -1293,7 +1293,6 @@ { rtx i1, i2, last1, last2, afterlast1, afterlast2; int ninsns = 0; - rtx p1; enum replace_direction dir, last_dir, afterlast_dir; bool follow_fallthru, did_fallthru; @@ -1321,8 +1320,9 @@ || (returnjump_p (i2) && !side_effects_p (PATTERN (i2)))) { last2 = i2; - /* Count everything except for unconditional jump as insn. */ - if (!simplejump_p (i2) && !returnjump_p (i2) && last1) + /* Count everything except for unconditional jump as insn. + Don't count any jumps if dir_p is NULL. */ + if (!simplejump_p (i2) && !returnjump_p (i2) && last1 && dir_p) ninsns++; i2 = PREV_INSN (i2); } @@ -1373,8 +1373,8 @@ last1 = i1, last2 = i2; afterlast_dir = last_dir; last_dir = dir; - p1 = PATTERN (i1); - if (!(GET_CODE (p1) == USE || GET_CODE (p1) == CLOBBER)) + if (GET_CODE (PATTERN (i1)) != USE + && GET_CODE (PATTERN (i1)) != CLOBBER) ninsns++; } @@ -1420,7 +1420,8 @@ /* Like flow_find_cross_jump, except start looking for a matching sequence from the head of the two blocks. Do not include jumps at the end. If STOP_AFTER is nonzero, stop after finding that many matching - instructions. */ + instructions. If STOP_AFTER is zero, count all INSN_P insns, if it is + non-zero, only count active insns. */ int flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, @@ -1492,7 +1493,10 @@ beforelast1 = last1, beforelast2 = last2; last1 = i1, last2 = i2; - ninsns++; + if (!stop_after + || (GET_CODE (PATTERN (i1)) != USE + && GET_CODE (PATTERN (i1)) != CLOBBER)) + ninsns++; } if (i1 == BB_END (bb1) || i2 == BB_END (bb2) diff -Naur gcc-4.8.2.orig/gcc/cfgexpand.c gcc-4.8.2/gcc/cfgexpand.c --- gcc-4.8.2.orig/gcc/cfgexpand.c 2013-03-05 22:31:50.000000000 +0000 +++ gcc-4.8.2/gcc/cfgexpand.c 2014-03-30 20:21:40.567596893 +0000 @@ -331,7 +331,7 @@ enter its partition number into bitmap DATA. */ static bool -visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +visit_op (gimple, tree op, tree, void *data) { bitmap active = (bitmap)data; op = get_base_address (op); @@ -351,7 +351,7 @@ from bitmap DATA. */ static bool -visit_conflict (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +visit_conflict (gimple, tree op, tree, void *data) { bitmap active = (bitmap)data; op = get_base_address (op); @@ -385,7 +385,7 @@ edge e; edge_iterator ei; gimple_stmt_iterator gsi; - bool (*visit)(gimple, tree, void *); + walk_stmt_load_store_addr_fn visit; bitmap_clear (work); FOR_EACH_EDGE (e, ei, bb->preds) @@ -4707,14 +4707,18 @@ if (e->insns.r) { rebuild_jump_labels_chain (e->insns.r); - /* Avoid putting insns before parm_birth_insn. */ + /* Put insns after parm birth, but before + NOTE_INSNS_FUNCTION_BEG. */ if (e->src == ENTRY_BLOCK_PTR - && single_succ_p (ENTRY_BLOCK_PTR) - && parm_birth_insn) + && single_succ_p (ENTRY_BLOCK_PTR)) { rtx insns = e->insns.r; e->insns.r = NULL_RTX; - emit_insn_after_noloc (insns, parm_birth_insn, e->dest); + if (NOTE_P (parm_birth_insn) + && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG) + emit_insn_before_noloc (insns, parm_birth_insn, e->dest); + else + emit_insn_after_noloc (insns, parm_birth_insn, e->dest); } else commit_one_edge_insertion (e); diff -Naur gcc-4.8.2.orig/gcc/cgraph.c gcc-4.8.2/gcc/cgraph.c --- gcc-4.8.2.orig/gcc/cgraph.c 2013-05-22 07:50:40.000000000 +0000 +++ gcc-4.8.2/gcc/cgraph.c 2014-03-30 20:21:40.567596893 +0000 @@ -2596,4 +2596,47 @@ FOR_EACH_FUNCTION (node) verify_cgraph_node (node); } + +/* Create external decl node for DECL. + The difference i nbetween cgraph_get_create_node and + cgraph_get_create_real_symbol_node is that cgraph_get_create_node + may return inline clone, while cgraph_get_create_real_symbol_node + will create a new node in this case. + FIXME: This function should be removed once clones are put out of decl + hash. */ + +struct cgraph_node * +cgraph_get_create_real_symbol_node (tree decl) +{ + struct cgraph_node *first_clone = cgraph_get_node (decl); + struct cgraph_node *node; + /* create symbol table node. even if inline clone exists, we can not take + it as a target of non-inlined call. */ + node = cgraph_get_node (decl); + if (node && !node->global.inlined_to) + return node; + + node = cgraph_create_node (decl); + + /* ok, we previously inlined the function, then removed the offline copy and + now we want it back for external call. this can happen when devirtualizing + while inlining function called once that happens after extern inlined and + virtuals are already removed. in this case introduce the external node + and make it available for call. */ + if (first_clone) + { + first_clone->clone_of = node; + node->clones = first_clone; + symtab_prevail_in_asm_name_hash ((symtab_node) node); + symtab_insert_node_to_hashtable ((symtab_node) node); + if (dump_file) + fprintf (dump_file, "Introduced new external node " + "(%s/%i) and turned into root of the clone tree.\n", + xstrdup (cgraph_node_name (node)), node->uid); + } + else if (dump_file) + fprintf (dump_file, "Introduced new external node " + "(%s/%i).\n", xstrdup (cgraph_node_name (node)), node->uid); + return node; +} #include "gt-cgraph.h" diff -Naur gcc-4.8.2.orig/gcc/cgraph.h gcc-4.8.2/gcc/cgraph.h --- gcc-4.8.2.orig/gcc/cgraph.h 2013-01-17 11:43:14.000000000 +0000 +++ gcc-4.8.2/gcc/cgraph.h 2014-03-30 20:21:40.567596893 +0000 @@ -575,6 +575,7 @@ struct cgraph_node * cgraph_create_node (tree); struct cgraph_node * cgraph_create_empty_node (void); struct cgraph_node * cgraph_get_create_node (tree); +struct cgraph_node * cgraph_get_create_real_symbol_node (tree); struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree); struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree); diff -Naur gcc-4.8.2.orig/gcc/cgraphbuild.c gcc-4.8.2/gcc/cgraphbuild.c --- gcc-4.8.2.orig/gcc/cgraphbuild.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/cgraphbuild.c 2014-03-30 20:21:40.567596893 +0000 @@ -73,7 +73,7 @@ decl = get_base_var (*tp); if (TREE_CODE (decl) == FUNCTION_DECL) { - struct cgraph_node *node = cgraph_get_create_node (decl); + struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl); if (!ctx->only_vars) cgraph_mark_address_taken_node (node); ipa_record_reference ((symtab_node)ctx->varpool_node, @@ -143,7 +143,7 @@ { struct cgraph_node *per_node; - per_node = cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl)); + per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl)); ipa_record_reference ((symtab_node)node, (symtab_node)per_node, IPA_REF_ADDR, NULL); cgraph_mark_address_taken_node (per_node); } @@ -218,12 +218,12 @@ /* Mark address taken in STMT. */ static bool -mark_address (gimple stmt, tree addr, void *data) +mark_address (gimple stmt, tree addr, tree, void *data) { addr = get_base_address (addr); if (TREE_CODE (addr) == FUNCTION_DECL) { - struct cgraph_node *node = cgraph_get_create_node (addr); + struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr); cgraph_mark_address_taken_node (node); ipa_record_reference ((symtab_node)data, (symtab_node)node, @@ -245,14 +245,14 @@ /* Mark load of T. */ static bool -mark_load (gimple stmt, tree t, void *data) +mark_load (gimple stmt, tree t, tree, void *data) { t = get_base_address (t); if (t && TREE_CODE (t) == FUNCTION_DECL) { /* ??? This can happen on platforms with descriptors when these are directly manipulated in the code. Pretend that it's an address. */ - struct cgraph_node *node = cgraph_get_create_node (t); + struct cgraph_node *node = cgraph_get_create_real_symbol_node (t); cgraph_mark_address_taken_node (node); ipa_record_reference ((symtab_node)data, (symtab_node)node, @@ -273,7 +273,7 @@ /* Mark store of T. */ static bool -mark_store (gimple stmt, tree t, void *data) +mark_store (gimple stmt, tree t, tree, void *data) { t = get_base_address (t); if (t && TREE_CODE (t) == VAR_DECL @@ -330,7 +330,7 @@ { tree fn = gimple_omp_parallel_child_fn (stmt); ipa_record_reference ((symtab_node)node, - (symtab_node)cgraph_get_create_node (fn), + (symtab_node)cgraph_get_create_real_symbol_node (fn), IPA_REF_ADDR, stmt); } if (gimple_code (stmt) == GIMPLE_OMP_TASK) @@ -338,12 +338,12 @@ tree fn = gimple_omp_task_child_fn (stmt); if (fn) ipa_record_reference ((symtab_node)node, - (symtab_node) cgraph_get_create_node (fn), + (symtab_node) cgraph_get_create_real_symbol_node (fn), IPA_REF_ADDR, stmt); fn = gimple_omp_task_copy_fn (stmt); if (fn) ipa_record_reference ((symtab_node)node, - (symtab_node)cgraph_get_create_node (fn), + (symtab_node)cgraph_get_create_real_symbol_node (fn), IPA_REF_ADDR, stmt); } } diff -Naur gcc-4.8.2.orig/gcc/combine.c gcc-4.8.2/gcc/combine.c --- gcc-4.8.2.orig/gcc/combine.c 2013-05-03 13:19:51.000000000 +0000 +++ gcc-4.8.2/gcc/combine.c 2014-03-30 20:21:40.567596893 +0000 @@ -3884,15 +3884,19 @@ PATTERN (undobuf.other_insn) = other_pat; - /* If any of the notes in OTHER_INSN were REG_UNUSED, ensure that they - are still valid. Then add any non-duplicate notes added by - recog_for_combine. */ + /* If any of the notes in OTHER_INSN were REG_DEAD or REG_UNUSED, + ensure that they are still valid. Then add any non-duplicate + notes added by recog_for_combine. */ for (note = REG_NOTES (undobuf.other_insn); note; note = next) { next = XEXP (note, 1); - if (REG_NOTE_KIND (note) == REG_UNUSED - && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn))) + if ((REG_NOTE_KIND (note) == REG_DEAD + && !reg_referenced_p (XEXP (note, 0), + PATTERN (undobuf.other_insn))) + ||(REG_NOTE_KIND (note) == REG_UNUSED + && !reg_set_p (XEXP (note, 0), + PATTERN (undobuf.other_insn)))) remove_note (undobuf.other_insn, note); } @@ -5798,8 +5802,15 @@ return x; } - /* If the code changed, return a whole new comparison. */ - if (new_code != code) + /* If the code changed, return a whole new comparison. + We also need to avoid using SUBST in cases where + simplify_comparison has widened a comparison with a CONST_INT, + since in that case the wider CONST_INT may fail the sanity + checks in do_SUBST. */ + if (new_code != code + || (CONST_INT_P (op1) + && GET_MODE (op0) != GET_MODE (XEXP (x, 0)) + && GET_MODE (op0) != GET_MODE (XEXP (x, 1)))) return gen_rtx_fmt_ee (new_code, mode, op0, op1); /* Otherwise, keep this operation, but maybe change its operands. @@ -7991,7 +8002,7 @@ if (code == CALL || code == ASM_OPERANDS || code == CLOBBER) return x; - /* We want to perform the operation is its present mode unless we know + /* We want to perform the operation in its present mode unless we know that the operation is valid in MODE, in which case we do the operation in MODE. */ op_mode = ((GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (x)) @@ -8427,9 +8438,10 @@ GET_MODE (x), GEN_INT (mask), XEXP (x, 1)); if (temp && CONST_INT_P (temp)) - SUBST (XEXP (x, 0), - force_to_mode (XEXP (x, 0), GET_MODE (x), - INTVAL (temp), next_select)); + x = simplify_gen_binary (code, GET_MODE (x), + force_to_mode (XEXP (x, 0), GET_MODE (x), + INTVAL (temp), next_select), + XEXP (x, 1)); } break; @@ -8497,14 +8509,16 @@ /* We have no way of knowing if the IF_THEN_ELSE can itself be written in a narrower mode. We play it safe and do not do so. */ - SUBST (XEXP (x, 1), - gen_lowpart_or_truncate (GET_MODE (x), - force_to_mode (XEXP (x, 1), mode, - mask, next_select))); - SUBST (XEXP (x, 2), - gen_lowpart_or_truncate (GET_MODE (x), - force_to_mode (XEXP (x, 2), mode, - mask, next_select))); + op0 = gen_lowpart_or_truncate (GET_MODE (x), + force_to_mode (XEXP (x, 1), mode, + mask, next_select)); + op1 = gen_lowpart_or_truncate (GET_MODE (x), + force_to_mode (XEXP (x, 2), mode, + mask, next_select)); + if (op0 != XEXP (x, 1) || op1 != XEXP (x, 2)) + x = simplify_gen_ternary (IF_THEN_ELSE, GET_MODE (x), + GET_MODE (XEXP (x, 0)), XEXP (x, 0), + op0, op1); break; default: diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/aarch64-simd-builtins.def gcc-4.8.2/gcc/config/aarch64/aarch64-simd-builtins.def --- gcc-4.8.2.orig/gcc/config/aarch64/aarch64-simd-builtins.def 2013-07-17 09:06:21.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/aarch64-simd-builtins.def 2014-03-30 20:21:40.574262822 +0000 @@ -217,8 +217,8 @@ BUILTIN_VSDQ_I_DI (BINOP, cmle) BUILTIN_VSDQ_I_DI (BINOP, cmlt) /* Implemented by aarch64_cm. */ - BUILTIN_VSDQ_I_DI (BINOP, cmhs) - BUILTIN_VSDQ_I_DI (BINOP, cmhi) + BUILTIN_VSDQ_I_DI (BINOP, cmgeu) + BUILTIN_VSDQ_I_DI (BINOP, cmgtu) BUILTIN_VSDQ_I_DI (BINOP, cmtst) /* Implemented by aarch64_. */ diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/aarch64-simd.md gcc-4.8.2/gcc/config/aarch64/aarch64-simd.md --- gcc-4.8.2.orig/gcc/config/aarch64/aarch64-simd.md 2013-07-17 09:06:21.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/aarch64-simd.md 2014-03-30 20:21:40.574262822 +0000 @@ -21,7 +21,7 @@ ; Main data types used by the insntructions -(define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,HI,QI" +(define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,SF,HI,QI" (const_string "unknown")) @@ -1548,12 +1548,12 @@ case LTU: case GEU: - emit_insn (gen_aarch64_cmhs (mask, operands[4], operands[5])); + emit_insn (gen_aarch64_cmgeu (mask, operands[4], operands[5])); break; case LEU: case GTU: - emit_insn (gen_aarch64_cmhi (mask, operands[4], operands[5])); + emit_insn (gen_aarch64_cmgtu (mask, operands[4], operands[5])); break; case NE: @@ -3034,48 +3034,181 @@ ) -;; cm(eq|ge|le|lt|gt) +;; cm(eq|ge|gt|lt|le) +;; Note, we have constraints for Dz and Z as different expanders +;; have different ideas of what should be passed to this pattern. -(define_insn "aarch64_cm" +(define_insn "aarch64_cm" [(set (match_operand: 0 "register_operand" "=w,w") - (unspec: - [(match_operand:VSDQ_I_DI 1 "register_operand" "w,w") - (match_operand:VSDQ_I_DI 2 "aarch64_simd_reg_or_zero" "w,Z")] - VCMP_S))] + (neg: + (COMPARISONS: + (match_operand:VDQ 1 "register_operand" "w,w") + (match_operand:VDQ 2 "aarch64_simd_reg_or_zero" "w,ZDz") + )))] "TARGET_SIMD" "@ - cm\t%0, %1, %2 - cm\t%0, %1, #0" + cm\t%0, %, % + cm\t%0, %1, #0" [(set_attr "simd_type" "simd_cmp") (set_attr "simd_mode" "")] ) -;; cm(hs|hi|tst) +(define_insn_and_split "aarch64_cmdi" + [(set (match_operand:DI 0 "register_operand" "=w,w,r") + (neg:DI + (COMPARISONS:DI + (match_operand:DI 1 "register_operand" "w,w,r") + (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz,r") + )))] + "TARGET_SIMD" + "@ + cm\t%d0, %d, %d + cm\t%d0, %d1, #0 + #" + "reload_completed + /* We need to prevent the split from + happening in the 'w' constraint cases. */ + && GP_REGNUM_P (REGNO (operands[0])) + && GP_REGNUM_P (REGNO (operands[1]))" + [(set (reg:CC CC_REGNUM) + (compare:CC + (match_dup 1) + (match_dup 2))) + (set (match_dup 0) + (neg:DI + (COMPARISONS:DI + (match_operand 3 "cc_register" "") + (const_int 0))))] + { + enum machine_mode mode = SELECT_CC_MODE (, operands[1], operands[2]); + rtx cc_reg = aarch64_gen_compare_reg (, operands[1], operands[2]); + rtx comparison = gen_rtx_ (mode, operands[1], operands[2]); + emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg)); + DONE; + } + [(set_attr "simd_type" "simd_cmp") + (set_attr "simd_mode" "DI")] +) + +;; cm(hs|hi) -(define_insn "aarch64_cm" +(define_insn "aarch64_cm" [(set (match_operand: 0 "register_operand" "=w") - (unspec: - [(match_operand:VSDQ_I_DI 1 "register_operand" "w") - (match_operand:VSDQ_I_DI 2 "register_operand" "w")] - VCMP_U))] + (neg: + (UCOMPARISONS: + (match_operand:VDQ 1 "register_operand" "w") + (match_operand:VDQ 2 "register_operand" "w") + )))] "TARGET_SIMD" - "cm\t%0, %1, %2" + "cm\t%0, %, %" [(set_attr "simd_type" "simd_cmp") (set_attr "simd_mode" "")] ) -;; fcm(eq|ge|le|lt|gt) +(define_insn_and_split "aarch64_cmdi" + [(set (match_operand:DI 0 "register_operand" "=w,r") + (neg:DI + (UCOMPARISONS:DI + (match_operand:DI 1 "register_operand" "w,r") + (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,r") + )))] + "TARGET_SIMD" + "@ + cm\t%d0, %d, %d + #" + "reload_completed + /* We need to prevent the split from + happening in the 'w' constraint cases. */ + && GP_REGNUM_P (REGNO (operands[0])) + && GP_REGNUM_P (REGNO (operands[1]))" + [(set (reg:CC CC_REGNUM) + (compare:CC + (match_dup 1) + (match_dup 2))) + (set (match_dup 0) + (neg:DI + (UCOMPARISONS:DI + (match_operand 3 "cc_register" "") + (const_int 0))))] + { + enum machine_mode mode = SELECT_CC_MODE (, operands[1], operands[2]); + rtx cc_reg = aarch64_gen_compare_reg (, operands[1], operands[2]); + rtx comparison = gen_rtx_ (mode, operands[1], operands[2]); + emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg)); + DONE; + } + [(set_attr "simd_type" "simd_cmp") + (set_attr "simd_mode" "DI")] +) + +;; cmtst + +(define_insn "aarch64_cmtst" + [(set (match_operand: 0 "register_operand" "=w") + (neg: + (ne: + (and:VDQ + (match_operand:VDQ 1 "register_operand" "w") + (match_operand:VDQ 2 "register_operand" "w")) + (vec_duplicate: (const_int 0)))))] + "TARGET_SIMD" + "cmtst\t%0, %1, %2" + [(set_attr "simd_type" "simd_cmp") + (set_attr "simd_mode" "")] +) + +(define_insn_and_split "aarch64_cmtstdi" + [(set (match_operand:DI 0 "register_operand" "=w,r") + (neg:DI + (ne:DI + (and:DI + (match_operand:DI 1 "register_operand" "w,r") + (match_operand:DI 2 "register_operand" "w,r")) + (const_int 0))))] + "TARGET_SIMD" + "@ + cmtst\t%d0, %d1, %d2 + #" + "reload_completed + /* We need to prevent the split from + happening in the 'w' constraint cases. */ + && GP_REGNUM_P (REGNO (operands[0])) + && GP_REGNUM_P (REGNO (operands[1]))" + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ + (and:DI (match_dup 1) + (match_dup 2)) + (const_int 0))) + (set (match_dup 0) + (neg:DI + (ne:DI + (match_operand 3 "cc_register" "") + (const_int 0))))] + { + rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]); + enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx); + rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx); + rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx); + emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg)); + DONE; + } + [(set_attr "simd_type" "simd_cmp") + (set_attr "simd_mode" "DI")] +) + +;; fcm(eq|ge|gt|le|lt) -(define_insn "aarch64_cm" +(define_insn "aarch64_cm" [(set (match_operand: 0 "register_operand" "=w,w") - (unspec: - [(match_operand:VDQF 1 "register_operand" "w,w") - (match_operand:VDQF 2 "aarch64_simd_reg_or_zero" "w,Dz")] - VCMP_S))] + (neg: + (COMPARISONS: + (match_operand:VALLF 1 "register_operand" "w,w") + (match_operand:VALLF 2 "aarch64_simd_reg_or_zero" "w,YDz") + )))] "TARGET_SIMD" "@ - fcm\t%0, %1, %2 - fcm\t%0, %1, 0" + fcm\t%0, %, % + fcm\t%0, %1, 0" [(set_attr "simd_type" "simd_fcmp") (set_attr "simd_mode" "")] ) diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/aarch64.c gcc-4.8.2/gcc/config/aarch64/aarch64.c --- gcc-4.8.2.orig/gcc/config/aarch64/aarch64.c 2013-06-03 15:33:09.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/aarch64.c 2014-03-30 20:21:40.570929878 +0000 @@ -2274,7 +2274,7 @@ if (ncount < zcount) { emit_move_insn (gen_rtx_REG (Pmode, regnum), - GEN_INT ((~val) & 0xffff)); + GEN_INT (val | ~(HOST_WIDE_INT) 0xffff)); tval = 0xffff; } else diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/aarch64.md gcc-4.8.2/gcc/config/aarch64/aarch64.md --- gcc-4.8.2.orig/gcc/config/aarch64/aarch64.md 2013-10-04 14:57:04.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/aarch64.md 2014-03-30 20:21:40.570929878 +0000 @@ -2211,7 +2211,7 @@ (set_attr "mode" "SI")] ) -(define_insn "*cstore_neg" +(define_insn "cstore_neg" [(set (match_operand:ALLI 0 "register_operand" "=r") (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator" [(match_operand 2 "cc_register" "") (const_int 0)])))] diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/arm_neon.h gcc-4.8.2/gcc/config/aarch64/arm_neon.h --- gcc-4.8.2.orig/gcc/config/aarch64/arm_neon.h 2013-10-12 08:23:31.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/arm_neon.h 2014-03-30 20:21:40.577595807 +0000 @@ -19551,28 +19551,28 @@ __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) vcge_u8 (uint8x8_t __a, uint8x8_t __b) { - return (uint8x8_t) __builtin_aarch64_cmhsv8qi ((int8x8_t) __a, + return (uint8x8_t) __builtin_aarch64_cmgeuv8qi ((int8x8_t) __a, (int8x8_t) __b); } __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) vcge_u16 (uint16x4_t __a, uint16x4_t __b) { - return (uint16x4_t) __builtin_aarch64_cmhsv4hi ((int16x4_t) __a, + return (uint16x4_t) __builtin_aarch64_cmgeuv4hi ((int16x4_t) __a, (int16x4_t) __b); } __extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) vcge_u32 (uint32x2_t __a, uint32x2_t __b) { - return (uint32x2_t) __builtin_aarch64_cmhsv2si ((int32x2_t) __a, + return (uint32x2_t) __builtin_aarch64_cmgeuv2si ((int32x2_t) __a, (int32x2_t) __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) vcge_u64 (uint64x1_t __a, uint64x1_t __b) { - return (uint64x1_t) __builtin_aarch64_cmhsdi ((int64x1_t) __a, + return (uint64x1_t) __builtin_aarch64_cmgeudi ((int64x1_t) __a, (int64x1_t) __b); } @@ -19603,28 +19603,28 @@ __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) vcgeq_u8 (uint8x16_t __a, uint8x16_t __b) { - return (uint8x16_t) __builtin_aarch64_cmhsv16qi ((int8x16_t) __a, + return (uint8x16_t) __builtin_aarch64_cmgeuv16qi ((int8x16_t) __a, (int8x16_t) __b); } __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) vcgeq_u16 (uint16x8_t __a, uint16x8_t __b) { - return (uint16x8_t) __builtin_aarch64_cmhsv8hi ((int16x8_t) __a, + return (uint16x8_t) __builtin_aarch64_cmgeuv8hi ((int16x8_t) __a, (int16x8_t) __b); } __extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) vcgeq_u32 (uint32x4_t __a, uint32x4_t __b) { - return (uint32x4_t) __builtin_aarch64_cmhsv4si ((int32x4_t) __a, + return (uint32x4_t) __builtin_aarch64_cmgeuv4si ((int32x4_t) __a, (int32x4_t) __b); } __extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) vcgeq_u64 (uint64x2_t __a, uint64x2_t __b) { - return (uint64x2_t) __builtin_aarch64_cmhsv2di ((int64x2_t) __a, + return (uint64x2_t) __builtin_aarch64_cmgeuv2di ((int64x2_t) __a, (int64x2_t) __b); } @@ -19637,7 +19637,7 @@ __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) vcged_u64 (uint64x1_t __a, uint64x1_t __b) { - return (uint64x1_t) __builtin_aarch64_cmhsdi ((int64x1_t) __a, + return (uint64x1_t) __builtin_aarch64_cmgeudi ((int64x1_t) __a, (int64x1_t) __b); } @@ -19676,28 +19676,28 @@ __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) vcgt_u8 (uint8x8_t __a, uint8x8_t __b) { - return (uint8x8_t) __builtin_aarch64_cmhiv8qi ((int8x8_t) __a, + return (uint8x8_t) __builtin_aarch64_cmgtuv8qi ((int8x8_t) __a, (int8x8_t) __b); } __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) vcgt_u16 (uint16x4_t __a, uint16x4_t __b) { - return (uint16x4_t) __builtin_aarch64_cmhiv4hi ((int16x4_t) __a, + return (uint16x4_t) __builtin_aarch64_cmgtuv4hi ((int16x4_t) __a, (int16x4_t) __b); } __extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) vcgt_u32 (uint32x2_t __a, uint32x2_t __b) { - return (uint32x2_t) __builtin_aarch64_cmhiv2si ((int32x2_t) __a, + return (uint32x2_t) __builtin_aarch64_cmgtuv2si ((int32x2_t) __a, (int32x2_t) __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) vcgt_u64 (uint64x1_t __a, uint64x1_t __b) { - return (uint64x1_t) __builtin_aarch64_cmhidi ((int64x1_t) __a, + return (uint64x1_t) __builtin_aarch64_cmgtudi ((int64x1_t) __a, (int64x1_t) __b); } @@ -19728,28 +19728,28 @@ __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) vcgtq_u8 (uint8x16_t __a, uint8x16_t __b) { - return (uint8x16_t) __builtin_aarch64_cmhiv16qi ((int8x16_t) __a, + return (uint8x16_t) __builtin_aarch64_cmgtuv16qi ((int8x16_t) __a, (int8x16_t) __b); } __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) vcgtq_u16 (uint16x8_t __a, uint16x8_t __b) { - return (uint16x8_t) __builtin_aarch64_cmhiv8hi ((int16x8_t) __a, + return (uint16x8_t) __builtin_aarch64_cmgtuv8hi ((int16x8_t) __a, (int16x8_t) __b); } __extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) vcgtq_u32 (uint32x4_t __a, uint32x4_t __b) { - return (uint32x4_t) __builtin_aarch64_cmhiv4si ((int32x4_t) __a, + return (uint32x4_t) __builtin_aarch64_cmgtuv4si ((int32x4_t) __a, (int32x4_t) __b); } __extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) vcgtq_u64 (uint64x2_t __a, uint64x2_t __b) { - return (uint64x2_t) __builtin_aarch64_cmhiv2di ((int64x2_t) __a, + return (uint64x2_t) __builtin_aarch64_cmgtuv2di ((int64x2_t) __a, (int64x2_t) __b); } @@ -19762,7 +19762,7 @@ __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) vcgtd_u64 (uint64x1_t __a, uint64x1_t __b) { - return (uint64x1_t) __builtin_aarch64_cmhidi ((int64x1_t) __a, + return (uint64x1_t) __builtin_aarch64_cmgtudi ((int64x1_t) __a, (int64x1_t) __b); } @@ -19801,28 +19801,28 @@ __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) vcle_u8 (uint8x8_t __a, uint8x8_t __b) { - return (uint8x8_t) __builtin_aarch64_cmhsv8qi ((int8x8_t) __b, + return (uint8x8_t) __builtin_aarch64_cmgeuv8qi ((int8x8_t) __b, (int8x8_t) __a); } __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) vcle_u16 (uint16x4_t __a, uint16x4_t __b) { - return (uint16x4_t) __builtin_aarch64_cmhsv4hi ((int16x4_t) __b, + return (uint16x4_t) __builtin_aarch64_cmgeuv4hi ((int16x4_t) __b, (int16x4_t) __a); } __extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) vcle_u32 (uint32x2_t __a, uint32x2_t __b) { - return (uint32x2_t) __builtin_aarch64_cmhsv2si ((int32x2_t) __b, + return (uint32x2_t) __builtin_aarch64_cmgeuv2si ((int32x2_t) __b, (int32x2_t) __a); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) vcle_u64 (uint64x1_t __a, uint64x1_t __b) { - return (uint64x1_t) __builtin_aarch64_cmhsdi ((int64x1_t) __b, + return (uint64x1_t) __builtin_aarch64_cmgeudi ((int64x1_t) __b, (int64x1_t) __a); } @@ -19853,28 +19853,28 @@ __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) vcleq_u8 (uint8x16_t __a, uint8x16_t __b) { - return (uint8x16_t) __builtin_aarch64_cmhsv16qi ((int8x16_t) __b, + return (uint8x16_t) __builtin_aarch64_cmgeuv16qi ((int8x16_t) __b, (int8x16_t) __a); } __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) vcleq_u16 (uint16x8_t __a, uint16x8_t __b) { - return (uint16x8_t) __builtin_aarch64_cmhsv8hi ((int16x8_t) __b, + return (uint16x8_t) __builtin_aarch64_cmgeuv8hi ((int16x8_t) __b, (int16x8_t) __a); } __extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) vcleq_u32 (uint32x4_t __a, uint32x4_t __b) { - return (uint32x4_t) __builtin_aarch64_cmhsv4si ((int32x4_t) __b, + return (uint32x4_t) __builtin_aarch64_cmgeuv4si ((int32x4_t) __b, (int32x4_t) __a); } __extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) vcleq_u64 (uint64x2_t __a, uint64x2_t __b) { - return (uint64x2_t) __builtin_aarch64_cmhsv2di ((int64x2_t) __b, + return (uint64x2_t) __builtin_aarch64_cmgeuv2di ((int64x2_t) __b, (int64x2_t) __a); } @@ -19919,28 +19919,28 @@ __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) vclt_u8 (uint8x8_t __a, uint8x8_t __b) { - return (uint8x8_t) __builtin_aarch64_cmhiv8qi ((int8x8_t) __b, + return (uint8x8_t) __builtin_aarch64_cmgtuv8qi ((int8x8_t) __b, (int8x8_t) __a); } __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) vclt_u16 (uint16x4_t __a, uint16x4_t __b) { - return (uint16x4_t) __builtin_aarch64_cmhiv4hi ((int16x4_t) __b, + return (uint16x4_t) __builtin_aarch64_cmgtuv4hi ((int16x4_t) __b, (int16x4_t) __a); } __extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) vclt_u32 (uint32x2_t __a, uint32x2_t __b) { - return (uint32x2_t) __builtin_aarch64_cmhiv2si ((int32x2_t) __b, + return (uint32x2_t) __builtin_aarch64_cmgtuv2si ((int32x2_t) __b, (int32x2_t) __a); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) vclt_u64 (uint64x1_t __a, uint64x1_t __b) { - return (uint64x1_t) __builtin_aarch64_cmhidi ((int64x1_t) __b, + return (uint64x1_t) __builtin_aarch64_cmgtudi ((int64x1_t) __b, (int64x1_t) __a); } @@ -19971,28 +19971,28 @@ __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) vcltq_u8 (uint8x16_t __a, uint8x16_t __b) { - return (uint8x16_t) __builtin_aarch64_cmhiv16qi ((int8x16_t) __b, + return (uint8x16_t) __builtin_aarch64_cmgtuv16qi ((int8x16_t) __b, (int8x16_t) __a); } __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) vcltq_u16 (uint16x8_t __a, uint16x8_t __b) { - return (uint16x8_t) __builtin_aarch64_cmhiv8hi ((int16x8_t) __b, + return (uint16x8_t) __builtin_aarch64_cmgtuv8hi ((int16x8_t) __b, (int16x8_t) __a); } __extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) vcltq_u32 (uint32x4_t __a, uint32x4_t __b) { - return (uint32x4_t) __builtin_aarch64_cmhiv4si ((int32x4_t) __b, + return (uint32x4_t) __builtin_aarch64_cmgtuv4si ((int32x4_t) __b, (int32x4_t) __a); } __extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) vcltq_u64 (uint64x2_t __a, uint64x2_t __b) { - return (uint64x2_t) __builtin_aarch64_cmhiv2di ((int64x2_t) __b, + return (uint64x2_t) __builtin_aarch64_cmgtuv2di ((int64x2_t) __b, (int64x2_t) __a); } diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/iterators.md gcc-4.8.2/gcc/config/aarch64/iterators.md --- gcc-4.8.2.orig/gcc/config/aarch64/iterators.md 2013-01-25 11:35:03.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/iterators.md 2014-03-30 20:21:40.577595807 +0000 @@ -83,6 +83,9 @@ ;; Vector Float modes. (define_mode_iterator VDQF [V2SF V4SF V2DF]) +;; All Float modes. +(define_mode_iterator VALLF [V2SF V4SF V2DF SF DF]) + ;; Vector Float modes with 2 elements. (define_mode_iterator V2F [V2SF V2DF]) @@ -213,13 +216,6 @@ UNSPEC_URSHL ; Used in aarch64-simd.md. UNSPEC_SQRSHL ; Used in aarch64-simd.md. UNSPEC_UQRSHL ; Used in aarch64-simd.md. - UNSPEC_CMEQ ; Used in aarch64-simd.md. - UNSPEC_CMLE ; Used in aarch64-simd.md. - UNSPEC_CMLT ; Used in aarch64-simd.md. - UNSPEC_CMGE ; Used in aarch64-simd.md. - UNSPEC_CMGT ; Used in aarch64-simd.md. - UNSPEC_CMHS ; Used in aarch64-simd.md. - UNSPEC_CMHI ; Used in aarch64-simd.md. UNSPEC_SSLI ; Used in aarch64-simd.md. UNSPEC_USLI ; Used in aarch64-simd.md. UNSPEC_SSRI ; Used in aarch64-simd.md. @@ -227,7 +223,6 @@ UNSPEC_SSHLL ; Used in aarch64-simd.md. UNSPEC_USHLL ; Used in aarch64-simd.md. UNSPEC_ADDP ; Used in aarch64-simd.md. - UNSPEC_CMTST ; Used in aarch64-simd.md. UNSPEC_FMAX ; Used in aarch64-simd.md. UNSPEC_FMIN ; Used in aarch64-simd.md. UNSPEC_BSL ; Used in aarch64-simd.md. @@ -251,6 +246,7 @@ ;; For scalar usage of vector/FP registers (define_mode_attr v [(QI "b") (HI "h") (SI "s") (DI "d") + (SF "s") (DF "d") (V8QI "") (V16QI "") (V4HI "") (V8HI "") (V2SI "") (V4SI "") @@ -305,7 +301,8 @@ (V4SF ".4s") (V2DF ".2d") (DI "") (SI "") (HI "") (QI "") - (TI "")]) + (TI "") (SF "") + (DF "")]) ;; Register suffix narrowed modes for VQN. (define_mode_attr Vmntype [(V8HI ".8b") (V4SI ".4h") @@ -444,7 +441,8 @@ (V2SI "V2SI") (V4SI "V4SI") (DI "DI") (V2DI "V2DI") (V2SF "V2SI") (V4SF "V4SI") - (V2DF "V2DI")]) + (V2DF "V2DI") (DF "DI") + (SF "SI")]) ;; Lower case mode of results of comparison operations. (define_mode_attr v_cmp_result [(V8QI "v8qi") (V16QI "v16qi") @@ -452,7 +450,8 @@ (V2SI "v2si") (V4SI "v4si") (DI "di") (V2DI "v2di") (V2SF "v2si") (V4SF "v4si") - (V2DF "v2di")]) + (V2DF "v2di") (DF "di") + (SF "si")]) ;; Vm for lane instructions is restricted to FP_LO_REGS. (define_mode_attr vwx [(V4HI "x") (V8HI "x") (HI "x") @@ -543,6 +542,12 @@ ;; Code iterator for signed variants of vector saturating binary ops. (define_code_iterator SBINQOPS [ss_plus ss_minus]) +;; Comparison operators for CM. +(define_code_iterator COMPARISONS [lt le eq ge gt]) + +;; Unsigned comparison operators. +(define_code_iterator UCOMPARISONS [ltu leu geu gtu]) + ;; ------------------------------------------------------------------- ;; Code Attributes ;; ------------------------------------------------------------------- @@ -571,7 +576,28 @@ (eq "eq") (ne "ne") (lt "lt") - (ge "ge")]) + (ge "ge") + (le "le") + (gt "gt") + (ltu "ltu") + (leu "leu") + (geu "geu") + (gtu "gtu")]) + +;; For comparison operators we use the FCM* and CM* instructions. +;; As there are no CMLE or CMLT instructions which act on 3 vector +;; operands, we must use CMGE or CMGT and swap the order of the +;; source operands. + +(define_code_attr n_optab [(lt "gt") (le "ge") (eq "eq") (ge "ge") (gt "gt") + (ltu "hi") (leu "hs") (geu "hs") (gtu "hi")]) +(define_code_attr cmp_1 [(lt "2") (le "2") (eq "1") (ge "1") (gt "1") + (ltu "2") (leu "2") (geu "1") (gtu "1")]) +(define_code_attr cmp_2 [(lt "1") (le "1") (eq "2") (ge "2") (gt "2") + (ltu "1") (leu "1") (geu "2") (gtu "2")]) + +(define_code_attr CMP [(lt "LT") (le "LE") (eq "EQ") (ge "GE") (gt "GT") + (ltu "LTU") (leu "LEU") (geu "GEU") (gtu "GTU")]) ;; Optab prefix for sign/zero-extending operations (define_code_attr su_optab [(sign_extend "") (zero_extend "u") @@ -680,11 +706,6 @@ UNSPEC_SQSHRN UNSPEC_UQSHRN UNSPEC_SQRSHRN UNSPEC_UQRSHRN]) -(define_int_iterator VCMP_S [UNSPEC_CMEQ UNSPEC_CMGE UNSPEC_CMGT - UNSPEC_CMLE UNSPEC_CMLT]) - -(define_int_iterator VCMP_U [UNSPEC_CMHS UNSPEC_CMHI UNSPEC_CMTST]) - (define_int_iterator PERMUTE [UNSPEC_ZIP1 UNSPEC_ZIP2 UNSPEC_TRN1 UNSPEC_TRN2 UNSPEC_UZP1 UNSPEC_UZP2]) @@ -768,12 +789,6 @@ (UNSPEC_RADDHN2 "add") (UNSPEC_RSUBHN2 "sub")]) -(define_int_attr cmp [(UNSPEC_CMGE "ge") (UNSPEC_CMGT "gt") - (UNSPEC_CMLE "le") (UNSPEC_CMLT "lt") - (UNSPEC_CMEQ "eq") - (UNSPEC_CMHS "hs") (UNSPEC_CMHI "hi") - (UNSPEC_CMTST "tst")]) - (define_int_attr offsetlr [(UNSPEC_SSLI "1") (UNSPEC_USLI "1") (UNSPEC_SSRI "0") (UNSPEC_USRI "0")]) diff -Naur gcc-4.8.2.orig/gcc/config/aarch64/predicates.md gcc-4.8.2/gcc/config/aarch64/predicates.md --- gcc-4.8.2.orig/gcc/config/aarch64/predicates.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/aarch64/predicates.md 2014-03-30 20:21:40.577595807 +0000 @@ -31,6 +31,11 @@ (ior (match_operand 0 "register_operand") (match_test "op == const0_rtx")))) +(define_predicate "aarch64_reg_or_fp_zero" + (and (match_code "reg,subreg,const_double") + (ior (match_operand 0 "register_operand") + (match_test "aarch64_float_const_zero_rtx_p (op)")))) + (define_predicate "aarch64_reg_zero_or_m1_or_1" (and (match_code "reg,subreg,const_int") (ior (match_operand 0 "register_operand") diff -Naur gcc-4.8.2.orig/gcc/config/arm/arm-ldmstm.ml gcc-4.8.2/gcc/config/arm/arm-ldmstm.ml --- gcc-4.8.2.orig/gcc/config/arm/arm-ldmstm.ml 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/arm-ldmstm.ml 2014-03-30 20:21:40.580928836 +0000 @@ -67,10 +67,13 @@ Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")") (nregs + 1) (inout_constr op_type) (constr thumb) +let reg_predicate thumb = + if thumb then "low_register_operand" else "arm_hard_general_register_operand" + let write_ldm_set thumb nregs offset opnr first = let indent = " " in Printf.printf "%s" (if first then " [" else indent); - Printf.printf "(set (match_operand:SI %d \"arm_hard_register_operand\" \"\")\n" opnr; + Printf.printf "(set (match_operand:SI %d \"%s\" \"\")\n" opnr (reg_predicate thumb); Printf.printf "%s (mem:SI " indent; begin if offset != 0 then Printf.printf "(plus:SI " end; Printf.printf "%s" (destreg nregs first IN thumb); @@ -84,7 +87,7 @@ begin if offset != 0 then Printf.printf "(plus:SI " end; Printf.printf "%s" (destreg nregs first IN thumb); begin if offset != 0 then Printf.printf " (const_int %d))" offset end; - Printf.printf ")\n%s (match_operand:SI %d \"arm_hard_register_operand\" \"\"))" indent opnr + Printf.printf ")\n%s (match_operand:SI %d \"%s\" \"\"))" indent opnr (reg_predicate thumb) let write_ldm_peep_set extra_indent nregs opnr first = let indent = " " ^ extra_indent in diff -Naur gcc-4.8.2.orig/gcc/config/arm/arm.c gcc-4.8.2/gcc/config/arm/arm.c --- gcc-4.8.2.orig/gcc/config/arm/arm.c 2013-09-18 16:37:35.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/arm.c 2014-03-30 20:21:40.580928836 +0000 @@ -5425,7 +5425,8 @@ if (!crtl->uses_pic_offset_table) { gcc_assert (can_create_pseudo_p ()); - if (arm_pic_register != INVALID_REGNUM) + if (arm_pic_register != INVALID_REGNUM + && !(TARGET_THUMB1 && arm_pic_register > LAST_LO_REGNUM)) { if (!cfun->machine->pic_reg) cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register); @@ -5451,7 +5452,12 @@ crtl->uses_pic_offset_table = 1; start_sequence (); - arm_load_pic_register (0UL); + if (TARGET_THUMB1 && arm_pic_register != INVALID_REGNUM + && arm_pic_register > LAST_LO_REGNUM) + emit_move_insn (cfun->machine->pic_reg, + gen_rtx_REG (Pmode, arm_pic_register)); + else + arm_load_pic_register (0UL); seq = get_insns (); end_sequence (); @@ -5709,6 +5715,14 @@ emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp)); emit_insn (gen_pic_add_dot_plus_four (pic_reg, pic_reg, labelno)); } + else if (arm_pic_register != INVALID_REGNUM + && arm_pic_register > LAST_LO_REGNUM + && REGNO (pic_reg) <= LAST_LO_REGNUM) + { + emit_insn (gen_pic_load_addr_unified (pic_reg, pic_rtx, labelno)); + emit_move_insn (gen_rtx_REG (Pmode, arm_pic_register), pic_reg); + emit_use (gen_rtx_REG (Pmode, arm_pic_register)); + } else emit_insn (gen_pic_load_addr_unified (pic_reg, pic_rtx, labelno)); } @@ -21279,7 +21293,11 @@ type_mode); } - op[argc] = expand_normal (arg[argc]); + /* Use EXPAND_MEMORY for NEON_ARG_MEMORY to ensure a MEM_P + be returned. */ + op[argc] = expand_expr (arg[argc], NULL_RTX, VOIDmode, + (thisarg == NEON_ARG_MEMORY + ? EXPAND_MEMORY : EXPAND_NORMAL)); switch (thisarg) { @@ -21298,6 +21316,9 @@ break; case NEON_ARG_MEMORY: + /* Check if expand failed. */ + if (op[argc] == const0_rtx) + return 0; gcc_assert (MEM_P (op[argc])); PUT_MODE (op[argc], mode[argc]); /* ??? arm_neon.h uses the same built-in functions for signed @@ -23555,6 +23576,7 @@ num_regs = bit_count (saved_regs_mask); if ((offsets->outgoing_args != (1 + num_regs)) || cfun->calls_alloca) { + emit_insn (gen_blockage ()); /* Unwind the stack to just below the saved registers. */ emit_insn (gen_addsi3 (stack_pointer_rtx, hard_frame_pointer_rtx, @@ -23583,8 +23605,8 @@ if (crtl->calls_eh_return) emit_insn (gen_addsi3 (stack_pointer_rtx, - stack_pointer_rtx, - GEN_INT (ARM_EH_STACKADJ_REGNUM))); + stack_pointer_rtx, + gen_rtx_REG (SImode, ARM_EH_STACKADJ_REGNUM))); if (IS_STACKALIGN (func_type)) /* Restore the original stack pointer. Before prologue, the stack was diff -Naur gcc-4.8.2.orig/gcc/config/arm/arm.h gcc-4.8.2/gcc/config/arm/arm.h --- gcc-4.8.2.orig/gcc/config/arm/arm.h 2013-03-17 16:28:55.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/arm.h 2014-03-30 20:21:40.580928836 +0000 @@ -1213,11 +1213,15 @@ VFPv2. In big-endian mode, modes greater than word size (i.e. DFmode) are stored in VFP registers in little-endian order. We can't describe that accurately to - GCC, so avoid taking subregs of such values. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ - (TARGET_VFP && TARGET_BIG_END \ - && (GET_MODE_SIZE (FROM) > UNITS_PER_WORD \ - || GET_MODE_SIZE (TO) > UNITS_PER_WORD) \ + GCC, so avoid taking subregs of such values. + The only exception is going from a 128-bit to a 64-bit type. In that case + the data layout happens to be consistent for big-endian, so we explicitly allow + that case. */ +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (TARGET_VFP && TARGET_BIG_END \ + && !(GET_MODE_SIZE (FROM) == 16 && GET_MODE_SIZE (TO) == 8) \ + && (GET_MODE_SIZE (FROM) > UNITS_PER_WORD \ + || GET_MODE_SIZE (TO) > UNITS_PER_WORD) \ && reg_classes_intersect_p (VFP_REGS, (CLASS))) /* The class value for index registers, and the one for base regs. */ diff -Naur gcc-4.8.2.orig/gcc/config/arm/arm.md gcc-4.8.2/gcc/config/arm/arm.md --- gcc-4.8.2.orig/gcc/config/arm/arm.md 2013-02-22 14:23:12.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/arm.md 2014-03-30 20:21:40.584261912 +0000 @@ -11036,7 +11036,7 @@ [(set (match_operand:SI 1 "s_register_operand" "+rk") (plus:SI (match_dup 1) (match_operand:SI 2 "const_int_operand" "I"))) - (set (match_operand:DF 3 "arm_hard_register_operand" "") + (set (match_operand:DF 3 "vfp_hard_register_operand" "") (mem:DF (match_dup 1)))])] "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" "* @@ -11270,7 +11270,9 @@ (match_operand:SI 1 "" "") (match_operand:SI 2 "" ""))] "TARGET_32BIT && arm_arch5e" - "pld\\t%a0") + "pld\\t%a0" + [(set_attr "type" "load1")] +) ;; General predication pattern diff -Naur gcc-4.8.2.orig/gcc/config/arm/iterators.md gcc-4.8.2/gcc/config/arm/iterators.md --- gcc-4.8.2.orig/gcc/config/arm/iterators.md 2013-04-04 14:34:01.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/iterators.md 2014-03-30 20:21:40.584261912 +0000 @@ -493,6 +493,10 @@ (UNSPEC_VRINTA "no") (UNSPEC_VRINTM "no") (UNSPEC_VRINTR "yes") (UNSPEC_VRINTX "yes")]) +(define_int_attr vrint_conds [(UNSPEC_VRINTZ "nocond") (UNSPEC_VRINTP "unconditional") + (UNSPEC_VRINTA "unconditional") (UNSPEC_VRINTM "unconditional") + (UNSPEC_VRINTR "nocond") (UNSPEC_VRINTX "nocond")]) + (define_int_attr nvrint_variant [(UNSPEC_NVRINTZ "z") (UNSPEC_NVRINTP "p") (UNSPEC_NVRINTA "a") (UNSPEC_NVRINTM "m") (UNSPEC_NVRINTX "x") (UNSPEC_NVRINTN "n")]) diff -Naur gcc-4.8.2.orig/gcc/config/arm/ldmstm.md gcc-4.8.2/gcc/config/arm/ldmstm.md --- gcc-4.8.2.orig/gcc/config/arm/ldmstm.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/ldmstm.md 2014-03-30 20:21:40.584261912 +0000 @@ -23,15 +23,15 @@ (define_insn "*ldm4_ia" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_operand:SI 5 "s_register_operand" "rk"))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 8)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" @@ -41,15 +41,15 @@ (define_insn "*thumb_ldm4_ia" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "low_register_operand" "") (mem:SI (match_operand:SI 5 "s_register_operand" "l"))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "low_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "low_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 8)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "low_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4" @@ -60,15 +60,15 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int 16))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_dup 5))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 8)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" @@ -80,15 +80,15 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 5 "s_register_operand" "+&l") (plus:SI (match_dup 5) (const_int 16))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "low_register_operand" "") (mem:SI (match_dup 5))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "low_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "low_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 8)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "low_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5" @@ -98,13 +98,13 @@ (define_insn "*stm4_ia" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (match_operand:SI 5 "s_register_operand" "rk")) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 8))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" "stm%(ia%)\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -115,13 +115,13 @@ [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int 16))) (set (mem:SI (match_dup 5)) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 8))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" "stm%(ia%)\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -132,29 +132,29 @@ [(set (match_operand:SI 5 "s_register_operand" "+&l") (plus:SI (match_dup 5) (const_int 16))) (set (mem:SI (match_dup 5)) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "low_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "low_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 8))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "low_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "low_register_operand" ""))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5" "stm%(ia%)\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4")]) (define_insn "*ldm4_ib" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 5 "s_register_operand" "rk") (const_int 4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 12)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 16))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" @@ -166,16 +166,16 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int 16))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 12)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int 16))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" @@ -186,13 +186,13 @@ (define_insn "*stm4_ib" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 5 "s_register_operand" "rk") (const_int 4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 16))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" "stm%(ib%)\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -203,13 +203,13 @@ [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int 16))) (set (mem:SI (plus:SI (match_dup 5) (const_int 4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int 16))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" "stm%(ib%)\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -217,16 +217,16 @@ (define_insn "*ldm4_da" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 5 "s_register_operand" "rk") (const_int -12)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -4)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (match_dup 5)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" "ldm%(da%)\t%5, {%1, %2, %3, %4}" @@ -237,16 +237,16 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int -16))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -12)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -4)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (match_dup 5)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" "ldm%(da%)\t%5!, {%1, %2, %3, %4}" @@ -256,13 +256,13 @@ (define_insn "*stm4_da" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 5 "s_register_operand" "rk") (const_int -12))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -4))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (match_dup 5)) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" "stm%(da%)\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -273,13 +273,13 @@ [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int -16))) (set (mem:SI (plus:SI (match_dup 5) (const_int -12))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -4))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (match_dup 5)) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" "stm%(da%)\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -287,16 +287,16 @@ (define_insn "*ldm4_db" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 5 "s_register_operand" "rk") (const_int -16)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -12)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -8)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" @@ -308,16 +308,16 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int -16))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -16)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -12)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -8)))) - (set (match_operand:SI 4 "arm_hard_register_operand" "") + (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 5) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" @@ -328,13 +328,13 @@ (define_insn "*stm4_db" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 5 "s_register_operand" "rk") (const_int -16))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -12))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -8))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -4))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" "stm%(db%)\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -345,13 +345,13 @@ [(set (match_operand:SI 5 "s_register_operand" "+&rk") (plus:SI (match_dup 5) (const_int -16))) (set (mem:SI (plus:SI (match_dup 5) (const_int -16))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -12))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -8))) - (match_operand:SI 3 "arm_hard_register_operand" "")) + (match_operand:SI 3 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 5) (const_int -4))) - (match_operand:SI 4 "arm_hard_register_operand" ""))])] + (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" "stm%(db%)\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") @@ -466,12 +466,12 @@ (define_insn "*ldm3_ia" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_operand:SI 4 "s_register_operand" "rk"))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" @@ -481,12 +481,12 @@ (define_insn "*thumb_ldm3_ia" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "low_register_operand" "") (mem:SI (match_operand:SI 4 "s_register_operand" "l"))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "low_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "low_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3" @@ -497,12 +497,12 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int 12))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_dup 4))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" @@ -514,12 +514,12 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 4 "s_register_operand" "+&l") (plus:SI (match_dup 4) (const_int 12))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "low_register_operand" "") (mem:SI (match_dup 4))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "low_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "low_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4" @@ -529,11 +529,11 @@ (define_insn "*stm3_ia" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (match_operand:SI 4 "s_register_operand" "rk")) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" "stm%(ia%)\t%4, {%1, %2, %3}" [(set_attr "type" "store3") @@ -544,11 +544,11 @@ [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int 12))) (set (mem:SI (match_dup 4)) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" "stm%(ia%)\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") @@ -559,24 +559,24 @@ [(set (match_operand:SI 4 "s_register_operand" "+&l") (plus:SI (match_dup 4) (const_int 12))) (set (mem:SI (match_dup 4)) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "low_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "low_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "low_register_operand" ""))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4" "stm%(ia%)\t%4!, {%1, %2, %3}" [(set_attr "type" "store3")]) (define_insn "*ldm3_ib" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 4 "s_register_operand" "rk") (const_int 4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 12))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" @@ -588,13 +588,13 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int 12))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int 12))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" @@ -605,11 +605,11 @@ (define_insn "*stm3_ib" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 4 "s_register_operand" "rk") (const_int 4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 12))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" "stm%(ib%)\t%4, {%1, %2, %3}" [(set_attr "type" "store3") @@ -620,11 +620,11 @@ [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int 12))) (set (mem:SI (plus:SI (match_dup 4) (const_int 4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int 12))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" "stm%(ib%)\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") @@ -632,13 +632,13 @@ (define_insn "*ldm3_da" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 4 "s_register_operand" "rk") (const_int -8)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (match_dup 4)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" "ldm%(da%)\t%4, {%1, %2, %3}" @@ -649,13 +649,13 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int -12))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -8)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -4)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (match_dup 4)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" "ldm%(da%)\t%4!, {%1, %2, %3}" @@ -665,11 +665,11 @@ (define_insn "*stm3_da" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 4 "s_register_operand" "rk") (const_int -8))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int -4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (match_dup 4)) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" "stm%(da%)\t%4, {%1, %2, %3}" [(set_attr "type" "store3") @@ -680,11 +680,11 @@ [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int -12))) (set (mem:SI (plus:SI (match_dup 4) (const_int -8))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int -4))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (match_dup 4)) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" "stm%(da%)\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") @@ -692,13 +692,13 @@ (define_insn "*ldm3_db" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 4 "s_register_operand" "rk") (const_int -12)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" @@ -710,13 +710,13 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int -12))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -12)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -8)))) - (set (match_operand:SI 3 "arm_hard_register_operand" "") + (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 4) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" @@ -727,11 +727,11 @@ (define_insn "*stm3_db" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 4 "s_register_operand" "rk") (const_int -12))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int -8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int -4))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" "stm%(db%)\t%4, {%1, %2, %3}" [(set_attr "type" "store3") @@ -742,11 +742,11 @@ [(set (match_operand:SI 4 "s_register_operand" "+&rk") (plus:SI (match_dup 4) (const_int -12))) (set (mem:SI (plus:SI (match_dup 4) (const_int -12))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int -8))) - (match_operand:SI 2 "arm_hard_register_operand" "")) + (match_operand:SI 2 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 4) (const_int -4))) - (match_operand:SI 3 "arm_hard_register_operand" ""))])] + (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" "stm%(db%)\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") @@ -847,9 +847,9 @@ (define_insn "*ldm2_ia" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_operand:SI 3 "s_register_operand" "rk"))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" @@ -859,9 +859,9 @@ (define_insn "*thumb_ldm2_ia" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "low_register_operand" "") (mem:SI (match_operand:SI 3 "s_register_operand" "l"))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "low_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2" @@ -872,9 +872,9 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int 8))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_dup 3))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" @@ -886,9 +886,9 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 3 "s_register_operand" "+&l") (plus:SI (match_dup 3) (const_int 8))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "low_register_operand" "") (mem:SI (match_dup 3))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "low_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3" @@ -898,9 +898,9 @@ (define_insn "*stm2_ia" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (match_operand:SI 3 "s_register_operand" "rk")) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" "stm%(ia%)\t%3, {%1, %2}" [(set_attr "type" "store2") @@ -911,9 +911,9 @@ [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int 8))) (set (mem:SI (match_dup 3)) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" "stm%(ia%)\t%3!, {%1, %2}" [(set_attr "type" "store2") @@ -924,19 +924,19 @@ [(set (match_operand:SI 3 "s_register_operand" "+&l") (plus:SI (match_dup 3) (const_int 8))) (set (mem:SI (match_dup 3)) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "low_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "low_register_operand" ""))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3" "stm%(ia%)\t%3!, {%1, %2}" [(set_attr "type" "store2")]) (define_insn "*ldm2_ib" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 3 "s_register_operand" "rk") (const_int 4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 8))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" @@ -948,10 +948,10 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int 8))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int 8))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" @@ -962,9 +962,9 @@ (define_insn "*stm2_ib" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 3 "s_register_operand" "rk") (const_int 4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int 8))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" "stm%(ib%)\t%3, {%1, %2}" [(set_attr "type" "store2") @@ -975,9 +975,9 @@ [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int 8))) (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int 8))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" "stm%(ib%)\t%3!, {%1, %2}" [(set_attr "type" "store2") @@ -985,10 +985,10 @@ (define_insn "*ldm2_da" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 3 "s_register_operand" "rk") (const_int -4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (match_dup 3)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" "ldm%(da%)\t%3, {%1, %2}" @@ -999,10 +999,10 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int -8))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int -4)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (match_dup 3)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" "ldm%(da%)\t%3!, {%1, %2}" @@ -1012,9 +1012,9 @@ (define_insn "*stm2_da" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 3 "s_register_operand" "rk") (const_int -4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (match_dup 3)) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" "stm%(da%)\t%3, {%1, %2}" [(set_attr "type" "store2") @@ -1025,9 +1025,9 @@ [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int -8))) (set (mem:SI (plus:SI (match_dup 3) (const_int -4))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (match_dup 3)) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" "stm%(da%)\t%3!, {%1, %2}" [(set_attr "type" "store2") @@ -1035,10 +1035,10 @@ (define_insn "*ldm2_db" [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "arm_hard_register_operand" "") + [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_operand:SI 3 "s_register_operand" "rk") (const_int -8)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" @@ -1050,10 +1050,10 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int -8))) - (set (match_operand:SI 1 "arm_hard_register_operand" "") + (set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int -8)))) - (set (match_operand:SI 2 "arm_hard_register_operand" "") + (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (plus:SI (match_dup 3) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" @@ -1064,9 +1064,9 @@ (define_insn "*stm2_db" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (plus:SI (match_operand:SI 3 "s_register_operand" "rk") (const_int -8))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int -4))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" "stm%(db%)\t%3, {%1, %2}" [(set_attr "type" "store2") @@ -1077,9 +1077,9 @@ [(set (match_operand:SI 3 "s_register_operand" "+&rk") (plus:SI (match_dup 3) (const_int -8))) (set (mem:SI (plus:SI (match_dup 3) (const_int -8))) - (match_operand:SI 1 "arm_hard_register_operand" "")) + (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int -4))) - (match_operand:SI 2 "arm_hard_register_operand" ""))])] + (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" "stm%(db%)\t%3!, {%1, %2}" [(set_attr "type" "store2") diff -Naur gcc-4.8.2.orig/gcc/config/arm/predicates.md gcc-4.8.2/gcc/config/arm/predicates.md --- gcc-4.8.2.orig/gcc/config/arm/predicates.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/predicates.md 2014-03-30 20:21:40.584261912 +0000 @@ -31,11 +31,11 @@ || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); }) -;; Any hard register. -(define_predicate "arm_hard_register_operand" +;; Any general register. +(define_predicate "arm_hard_general_register_operand" (match_code "reg") { - return REGNO (op) < FIRST_PSEUDO_REGISTER; + return REGNO (op) <= LAST_ARM_REGNUM; }) ;; A low register. @@ -76,6 +76,12 @@ && REGNO_REG_CLASS (REGNO (op)) == VFP_REGS))); }) +(define_predicate "vfp_hard_register_operand" + (match_code "reg") +{ + return (IS_VFP_REGNUM (REGNO (op))); +}) + (define_predicate "zero_operand" (and (match_code "const_int,const_double,const_vector") (match_test "op == CONST0_RTX (mode)"))) diff -Naur gcc-4.8.2.orig/gcc/config/arm/vfp.md gcc-4.8.2/gcc/config/arm/vfp.md --- gcc-4.8.2.orig/gcc/config/arm/vfp.md 2013-09-10 16:53:15.000000000 +0000 +++ gcc-4.8.2/gcc/config/arm/vfp.md 2014-03-30 20:21:40.584261912 +0000 @@ -1264,6 +1264,7 @@ "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 " "vrint%?.\\t%0, %1" [(set_attr "predicable" "") + (set_attr "conds" "") (set_attr "type" "f_rint")] ) @@ -1280,7 +1281,8 @@ (match_operand:SDF 2 "register_operand" "")))] "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 " "vmaxnm.\\t%0, %1, %2" - [(set_attr "type" "f_minmax")] + [(set_attr "type" "f_minmax") + (set_attr "conds" "unconditional")] ) (define_insn "smin3" @@ -1289,7 +1291,8 @@ (match_operand:SDF 2 "register_operand" "")))] "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 " "vminnm.\\t%0, %1, %2" - [(set_attr "type" "f_minmax")] + [(set_attr "type" "f_minmax") + (set_attr "conds" "unconditional")] ) ;; Unimplemented insns: diff -Naur gcc-4.8.2.orig/gcc/config/avr/avr.c gcc-4.8.2/gcc/config/avr/avr.c --- gcc-4.8.2.orig/gcc/config/avr/avr.c 2013-07-19 11:15:26.000000000 +0000 +++ gcc-4.8.2/gcc/config/avr/avr.c 2014-03-30 20:21:40.587595031 +0000 @@ -587,10 +587,14 @@ const char *name; name = DECL_ASSEMBLER_NAME_SET_P (decl) - /* Remove the leading '*' added in set_user_assembler_name. */ - ? 1 + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) + ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) : IDENTIFIER_POINTER (DECL_NAME (decl)); + /* Skip a leading '*' that might still prefix the assembler name, + e.g. in non-LTO runs. */ + + name = default_strip_name_encoding (name); + /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet using this when it switched from SIGNAL and INTERRUPT to ISR. */ @@ -6806,8 +6810,8 @@ /* Work out the shortest sequence. */ - avr_out_plus_1 (op, &len_minus, MINUS, &cc_plus, code_sat, sign, out_label); - avr_out_plus_1 (op, &len_plus, PLUS, &cc_minus, code_sat, sign, out_label); + avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label); + avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label); if (plen) { diff -Naur gcc-4.8.2.orig/gcc/config/cris/cris.md gcc-4.8.2/gcc/config/cris/cris.md --- gcc-4.8.2.orig/gcc/config/cris/cris.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/cris/cris.md 2014-03-30 20:21:40.587595031 +0000 @@ -758,7 +758,7 @@ (match_operand:SI 1 "const_int_operand" "")) (match_operand:SI 2 "register_operand" ""))]) (match_operand 3 "register_operand" "")) - (set (match_operand:SI 4 "register_operand" "") + (set (match_operand:SI 4 "cris_nonsp_register_operand" "") (plus:SI (mult:SI (match_dup 0) (match_dup 1)) (match_dup 2)))])] @@ -859,7 +859,7 @@ (match_operand:SI 0 "cris_bdap_operand" "") (match_operand:SI 1 "cris_bdap_operand" ""))]) (match_operand 2 "register_operand" "")) - (set (match_operand:SI 3 "register_operand" "") + (set (match_operand:SI 3 "cris_nonsp_register_operand" "") (plus:SI (match_dup 0) (match_dup 1)))])] "reload_completed && reg_overlap_mentioned_p (operands[3], operands[2])" [(set (match_dup 4) (match_dup 2)) @@ -3960,7 +3960,7 @@ ;; up. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 4 "cris_operand_extend_operator" [(match_operand 1 "register_operand" "") @@ -3990,7 +3990,7 @@ ;; Call this op-extend-split-rx=rz (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 4 "cris_plus_or_bound_operator" [(match_operand 1 "register_operand" "") @@ -4018,7 +4018,7 @@ ;; Call this op-extend-split-swapped (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 4 "cris_plus_or_bound_operator" [(match_operator @@ -4044,7 +4044,7 @@ ;; bound. Call this op-extend-split-swapped-rx=rz. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 4 "cris_plus_or_bound_operator" [(match_operator @@ -4075,7 +4075,7 @@ ;; Call this op-extend. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 3 "cris_orthogonal_operator" [(match_operand 1 "register_operand" "") @@ -4099,7 +4099,7 @@ ;; Call this op-split-rx=rz (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 3 "cris_commutative_orth_op" [(match_operand 2 "memory_operand" "") @@ -4123,7 +4123,7 @@ ;; Call this op-split-swapped. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 3 "cris_commutative_orth_op" [(match_operand 1 "register_operand" "") @@ -4146,7 +4146,7 @@ ;; Call this op-split-swapped-rx=rz. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 3 "cris_orthogonal_operator" [(match_operand 2 "memory_operand" "") @@ -4555,10 +4555,11 @@ ;; We're not allowed to generate copies of registers with different mode ;; until after reload; copying pseudos upsets reload. CVS as of ;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in -;; cselib_invalidate_regno. +;; cselib_invalidate_regno. Also, don't do this for the stack-pointer, +;; as we don't want it set temporarily to an invalid value. (define_split ; indir_to_reg_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operand 1 "indirect_operand" ""))] "reload_completed && REG_P (operands[0]) @@ -4574,7 +4575,7 @@ ;; As the above, but MOVS and MOVU. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "cris_nonsp_register_operand" "") (match_operator 4 "cris_extend_operator" [(match_operand 1 "indirect_operand" "")]))] diff -Naur gcc-4.8.2.orig/gcc/config/cris/predicates.md gcc-4.8.2/gcc/config/cris/predicates.md --- gcc-4.8.2.orig/gcc/config/cris/predicates.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/cris/predicates.md 2014-03-30 20:21:40.587595031 +0000 @@ -76,6 +76,10 @@ (match_test "cris_simple_address_operand (XEXP (op, 0), Pmode)")))) +(define_predicate "cris_nonsp_register_operand" + (and (match_operand 0 "register_operand") + (match_test "op != stack_pointer_rtx"))) + ;; The caller needs to use :SI. (define_predicate "cris_bdap_sign_extend_operand" ; Disabled until diff -Naur gcc-4.8.2.orig/gcc/config/i386/driver-i386.c gcc-4.8.2/gcc/config/i386/driver-i386.c --- gcc-4.8.2.orig/gcc/config/i386/driver-i386.c 2013-08-28 08:25:13.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/driver-i386.c 2014-03-30 20:21:40.587595031 +0000 @@ -126,6 +126,18 @@ case 0x0c: level1->sizekb = 16; level1->assoc = 4; level1->line = 32; break; + case 0x0d: + level1->sizekb = 16; level1->assoc = 4; level1->line = 64; + break; + case 0x0e: + level1->sizekb = 24; level1->assoc = 6; level1->line = 64; + break; + case 0x21: + level2->sizekb = 256; level2->assoc = 8; level2->line = 64; + break; + case 0x24: + level2->sizekb = 1024; level2->assoc = 16; level2->line = 64; + break; case 0x2c: level1->sizekb = 32; level1->assoc = 8; level1->line = 64; break; @@ -162,6 +174,9 @@ case 0x45: level2->sizekb = 2048; level2->assoc = 4; level2->line = 32; break; + case 0x48: + level2->sizekb = 3072; level2->assoc = 12; level2->line = 64; + break; case 0x49: if (xeon_mp) break; @@ -203,6 +218,9 @@ case 0x7f: level2->sizekb = 512; level2->assoc = 2; level2->line = 64; break; + case 0x80: + level2->sizekb = 512; level2->assoc = 8; level2->line = 64; + break; case 0x82: level2->sizekb = 256; level2->assoc = 8; level2->line = 32; break; @@ -470,6 +488,28 @@ has_xsaveopt = eax & bit_XSAVEOPT; } + /* Check cpuid level of extended features. */ + __cpuid (0x80000000, ext_level, ebx, ecx, edx); + + if (ext_level > 0x80000000) + { + __cpuid (0x80000001, eax, ebx, ecx, edx); + + has_lahf_lm = ecx & bit_LAHF_LM; + has_sse4a = ecx & bit_SSE4a; + has_abm = ecx & bit_ABM; + has_lwp = ecx & bit_LWP; + has_fma4 = ecx & bit_FMA4; + has_xop = ecx & bit_XOP; + has_tbm = ecx & bit_TBM; + has_lzcnt = ecx & bit_LZCNT; + has_prfchw = ecx & bit_PRFCHW; + + has_longmode = edx & bit_LM; + has_3dnowp = edx & bit_3DNOWP; + has_3dnow = edx & bit_3DNOW; + } + /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */ #define XCR_XFEATURE_ENABLED_MASK 0x0 #define XSTATE_FP 0x1 @@ -488,33 +528,12 @@ has_avx2 = 0; has_fma = 0; has_fma4 = 0; + has_f16c = 0; has_xop = 0; has_xsave = 0; has_xsaveopt = 0; } - /* Check cpuid level of extended features. */ - __cpuid (0x80000000, ext_level, ebx, ecx, edx); - - if (ext_level > 0x80000000) - { - __cpuid (0x80000001, eax, ebx, ecx, edx); - - has_lahf_lm = ecx & bit_LAHF_LM; - has_sse4a = ecx & bit_SSE4a; - has_abm = ecx & bit_ABM; - has_lwp = ecx & bit_LWP; - has_fma4 = ecx & bit_FMA4; - has_xop = ecx & bit_XOP; - has_tbm = ecx & bit_TBM; - has_lzcnt = ecx & bit_LZCNT; - has_prfchw = ecx & bit_PRFCHW; - - has_longmode = edx & bit_LM; - has_3dnowp = edx & bit_3DNOWP; - has_3dnow = edx & bit_3DNOW; - } - if (!arch) { if (vendor == signature_AMD_ebx diff -Naur gcc-4.8.2.orig/gcc/config/i386/f16cintrin.h gcc-4.8.2/gcc/config/i386/f16cintrin.h --- gcc-4.8.2.orig/gcc/config/i386/f16cintrin.h 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/f16cintrin.h 2014-03-30 20:21:40.587595031 +0000 @@ -35,7 +35,7 @@ extern __inline float __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _cvtsh_ss (unsigned short __S) { - __v8hi __H = __extension__ (__v8hi){ __S, 0, 0, 0, 0, 0, 0, 0 }; + __v8hi __H = __extension__ (__v8hi){ (short) __S, 0, 0, 0, 0, 0, 0, 0 }; __v4sf __A = __builtin_ia32_vcvtph2ps (__H); return __builtin_ia32_vec_ext_v4sf (__A, 0); } diff -Naur gcc-4.8.2.orig/gcc/config/i386/i386.c gcc-4.8.2/gcc/config/i386/i386.c --- gcc-4.8.2.orig/gcc/config/i386/i386.c 2013-08-23 10:01:34.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/i386.c 2014-03-30 20:21:40.594261397 +0000 @@ -1378,7 +1378,7 @@ 8, /* MMX or SSE register to integer */ 8, /* size of l1 cache. */ 1024, /* size of l2 cache. */ - 128, /* size of prefetch block */ + 64, /* size of prefetch block */ 8, /* number of parallel prefetches */ 1, /* Branch cost */ COSTS_N_INSNS (6), /* cost of FADD and FSUB insns. */ @@ -1894,10 +1894,10 @@ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_AMDFAM10 | m_BDVER | m_GENERIC, /* X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL */ - m_COREI7 | m_AMDFAM10 | m_BDVER | m_BTVER, + m_COREI7 | m_HASWELL | m_AMDFAM10 | m_BDVER | m_BTVER, /* X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL */ - m_COREI7 | m_BDVER, + m_COREI7 | m_HASWELL| m_BDVER, /* X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL */ m_BDVER , @@ -2409,6 +2409,7 @@ /* Processor target table, indexed by processor number */ struct ptt { + const char *const name; /* processor name */ const struct processor_costs *cost; /* Processor costs */ const int align_loop; /* Default alignments. */ const int align_loop_max_skip; @@ -2417,66 +2418,31 @@ const int align_func; }; +/* This table must be in sync with enum processor_type in i386.h. */ static const struct ptt processor_target_table[PROCESSOR_max] = { - {&i386_cost, 4, 3, 4, 3, 4}, - {&i486_cost, 16, 15, 16, 15, 16}, - {&pentium_cost, 16, 7, 16, 7, 16}, - {&pentiumpro_cost, 16, 15, 16, 10, 16}, - {&geode_cost, 0, 0, 0, 0, 0}, - {&k6_cost, 32, 7, 32, 7, 32}, - {&athlon_cost, 16, 7, 16, 7, 16}, - {&pentium4_cost, 0, 0, 0, 0, 0}, - {&k8_cost, 16, 7, 16, 7, 16}, - {&nocona_cost, 0, 0, 0, 0, 0}, - /* Core 2 */ - {&core_cost, 16, 10, 16, 10, 16}, - /* Core i7 */ - {&core_cost, 16, 10, 16, 10, 16}, - /* Core avx2 */ - {&core_cost, 16, 10, 16, 10, 16}, - {&generic32_cost, 16, 7, 16, 7, 16}, - {&generic64_cost, 16, 10, 16, 10, 16}, - {&amdfam10_cost, 32, 24, 32, 7, 32}, - {&bdver1_cost, 16, 10, 16, 7, 11}, - {&bdver2_cost, 16, 10, 16, 7, 11}, - {&bdver3_cost, 16, 10, 16, 7, 11}, - {&btver1_cost, 16, 10, 16, 7, 11}, - {&btver2_cost, 16, 10, 16, 7, 11}, - {&atom_cost, 16, 15, 16, 7, 16} -}; - -static const char *const cpu_names[TARGET_CPU_DEFAULT_max] = -{ - "generic", - "i386", - "i486", - "pentium", - "pentium-mmx", - "pentiumpro", - "pentium2", - "pentium3", - "pentium4", - "pentium-m", - "prescott", - "nocona", - "core2", - "corei7", - "core-avx2", - "atom", - "geode", - "k6", - "k6-2", - "k6-3", - "athlon", - "athlon-4", - "k8", - "amdfam10", - "bdver1", - "bdver2", - "bdver3", - "btver1", - "btver2" + {"generic", &generic32_cost, 16, 7, 16, 7, 16}, + {"generic", &generic64_cost, 16, 10, 16, 10, 16}, + {"i386", &i386_cost, 4, 3, 4, 3, 4}, + {"i486", &i486_cost, 16, 15, 16, 15, 16}, + {"pentium", &pentium_cost, 16, 7, 16, 7, 16}, + {"pentiumpro", &pentiumpro_cost, 16, 15, 16, 10, 16}, + {"pentium4", &pentium4_cost, 0, 0, 0, 0, 0}, + {"nocona", &nocona_cost, 0, 0, 0, 0, 0}, + {"core2", &core_cost, 16, 10, 16, 10, 16}, + {"corei7", &core_cost, 16, 10, 16, 10, 16}, + {"core-avx2", &core_cost, 16, 10, 16, 10, 16}, + {"atom", &atom_cost, 16, 15, 16, 7, 16}, + {"geode", &geode_cost, 0, 0, 0, 0, 0}, + {"k6", &k6_cost, 32, 7, 32, 7, 32}, + {"athlon", &athlon_cost, 16, 7, 16, 7, 16}, + {"k8", &k8_cost, 16, 7, 16, 7, 16}, + {"amdfam10", &amdfam10_cost, 32, 24, 32, 7, 32}, + {"bdver1", &bdver1_cost, 16, 10, 16, 7, 11}, + {"bdver2", &bdver2_cost, 16, 10, 16, 7, 11}, + {"bdver3", &bdver3_cost, 16, 10, 16, 7, 11}, + {"btver1", &btver1_cost, 16, 10, 16, 7, 11}, + {"btver2", &btver2_cost, 16, 10, 16, 7, 11} }; static bool @@ -2983,7 +2949,7 @@ {"bdver3", PROCESSOR_BDVER3, CPU_BDVER3, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 - | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX + | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT}, @@ -3125,7 +3091,8 @@ ix86_tune_string = ix86_arch_string; if (!ix86_tune_string) { - ix86_tune_string = cpu_names[TARGET_CPU_DEFAULT]; + ix86_tune_string + = processor_target_table[TARGET_CPU_DEFAULT].name; ix86_tune_defaulted = 1; } @@ -4078,19 +4045,15 @@ = ix86_target_string (ptr->x_ix86_isa_flags, ptr->x_target_flags, NULL, NULL, ptr->x_ix86_fpmath, false); + gcc_assert (ptr->arch < PROCESSOR_max); fprintf (file, "%*sarch = %d (%s)\n", indent, "", - ptr->arch, - ((ptr->arch < TARGET_CPU_DEFAULT_max) - ? cpu_names[ptr->arch] - : "")); + ptr->arch, processor_target_table[ptr->arch].name); + gcc_assert (ptr->tune < PROCESSOR_max); fprintf (file, "%*stune = %d (%s)\n", indent, "", - ptr->tune, - ((ptr->tune < TARGET_CPU_DEFAULT_max) - ? cpu_names[ptr->tune] - : "")); + ptr->tune, processor_target_table[ptr->tune].name); fprintf (file, "%*sbranch_cost = %d\n", indent, "", ptr->branch_cost); @@ -5213,7 +5176,12 @@ /* Use register calling convention for local functions when possible. */ if (decl && TREE_CODE (decl) == FUNCTION_DECL - && optimize + /* Caller and callee must agree on the calling convention, so + checking here just optimize means that with + __attribute__((optimize (...))) caller could use regparm convention + and callee not, or vice versa. Instead look at whether the callee + is optimized or not. */ + && opt_for_fn (decl, optimize) && !(profile_flag && !flag_fentry)) { /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified. */ @@ -5409,6 +5377,17 @@ bool win; int j; + /* For pre-AVX disallow unaligned loads/stores where the + instructions don't support it. */ + if (!TARGET_AVX + && VECTOR_MODE_P (GET_MODE (op)) + && misaligned_operand (op, GET_MODE (op))) + { + int min_align = get_attr_ssememalign (insn); + if (min_align == 0) + return false; + } + /* A unary operator may be accepted by the predicate, but it is irrelevant for matching constraints. */ if (UNARY_P (op)) @@ -5747,9 +5726,9 @@ cum->nregs = 0; cum->sse_nregs = 0; cum->mmx_nregs = 0; - cum->warn_avx = 0; - cum->warn_sse = 0; - cum->warn_mmx = 0; + cum->warn_avx = false; + cum->warn_sse = false; + cum->warn_mmx = false; return; } @@ -5790,10 +5769,14 @@ The midde-end can't deal with the vector types > 16 bytes. In this case, we return the original mode and warn ABI change if CUM isn't - NULL. */ + NULL. + + If INT_RETURN is true, warn ABI change if the vector mode isn't + available for function return value. */ static enum machine_mode -type_natural_mode (const_tree type, const CUMULATIVE_ARGS *cum) +type_natural_mode (const_tree type, const CUMULATIVE_ARGS *cum, + bool in_return) { enum machine_mode mode = TYPE_MODE (type); @@ -5819,33 +5802,61 @@ if (size == 32 && !TARGET_AVX) { static bool warnedavx; + static bool warnedavx_ret; - if (cum - && !warnedavx - && cum->warn_avx) + if (cum && cum->warn_avx && !warnedavx) { - warnedavx = true; - warning (0, "AVX vector argument without AVX " - "enabled changes the ABI"); + if (warning (OPT_Wpsabi, "AVX vector argument " + "without AVX enabled changes the ABI")) + warnedavx = true; } + else if (in_return && !warnedavx_ret) + { + if (warning (OPT_Wpsabi, "AVX vector return " + "without AVX enabled changes the ABI")) + warnedavx_ret = true; + } + return TYPE_MODE (type); } - else if ((size == 8 || size == 16) && !TARGET_SSE) + else if (((size == 8 && TARGET_64BIT) || size == 16) + && !TARGET_SSE) { static bool warnedsse; + static bool warnedsse_ret; - if (cum - && !warnedsse - && cum->warn_sse) + if (cum && cum->warn_sse && !warnedsse) { - warnedsse = true; - warning (0, "SSE vector argument without SSE " - "enabled changes the ABI"); + if (warning (OPT_Wpsabi, "SSE vector argument " + "without SSE enabled changes the ABI")) + warnedsse = true; + } + else if (!TARGET_64BIT && in_return && !warnedsse_ret) + { + if (warning (OPT_Wpsabi, "SSE vector return " + "without SSE enabled changes the ABI")) + warnedsse_ret = true; } - return mode; } - else - return mode; + else if ((size == 8 && !TARGET_64BIT) && !TARGET_MMX) + { + static bool warnedmmx; + static bool warnedmmx_ret; + + if (cum && cum->warn_mmx && !warnedmmx) + { + if (warning (OPT_Wpsabi, "MMX vector argument " + "without MMX enabled changes the ABI")) + warnedmmx = true; + } + else if (in_return && !warnedmmx_ret) + { + if (warning (OPT_Wpsabi, "MMX vector return " + "without MMX enabled changes the ABI")) + warnedmmx_ret = true; + } + } + return mode; } gcc_unreachable (); @@ -6190,25 +6201,28 @@ case CHImode: case CQImode: { - int size = (bit_offset % 64)+ (int) GET_MODE_BITSIZE (mode); + int size = bit_offset + (int) GET_MODE_BITSIZE (mode); + + /* Analyze last 128 bits only. */ + size = (size - 1) & 0x7f; - if (size <= 32) + if (size < 32) { classes[0] = X86_64_INTEGERSI_CLASS; return 1; } - else if (size <= 64) + else if (size < 64) { classes[0] = X86_64_INTEGER_CLASS; return 1; } - else if (size <= 64+32) + else if (size < 64+32) { classes[0] = X86_64_INTEGER_CLASS; classes[1] = X86_64_INTEGERSI_CLASS; return 2; } - else if (size <= 64+64) + else if (size < 64+64) { classes[0] = classes[1] = X86_64_INTEGER_CLASS; return 2; @@ -6475,7 +6489,7 @@ if (n == 2 && regclass[0] == X86_64_INTEGER_CLASS && regclass[1] == X86_64_INTEGER_CLASS - && (mode == CDImode || mode == TImode || mode == TFmode) + && (mode == CDImode || mode == TImode) && intreg[0] + 1 == intreg[1]) return gen_rtx_REG (mode, intreg[0]); @@ -6725,7 +6739,7 @@ words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (type) - mode = type_natural_mode (type, NULL); + mode = type_natural_mode (type, NULL, false); if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) function_arg_advance_ms_64 (cum, bytes, words); @@ -6753,8 +6767,6 @@ enum machine_mode orig_mode, const_tree type, HOST_WIDE_INT bytes, HOST_WIDE_INT words) { - static bool warnedsse, warnedmmx; - /* Avoid the AL settings for the Unix64 ABI. */ if (mode == VOIDmode) return constm1_rtx; @@ -6811,12 +6823,6 @@ case V2DFmode: if (!type || !AGGREGATE_TYPE_P (type)) { - if (!TARGET_SSE && !warnedsse && cum->warn_sse) - { - warnedsse = true; - warning (0, "SSE vector argument without SSE enabled " - "changes the ABI"); - } if (cum->sse_nregs) return gen_reg_or_parallel (mode, orig_mode, cum->sse_regno + FIRST_SSE_REG); @@ -6849,12 +6855,6 @@ case V1DImode: if (!type || !AGGREGATE_TYPE_P (type)) { - if (!TARGET_MMX && !warnedmmx && cum->warn_mmx) - { - warnedmmx = true; - warning (0, "MMX vector argument without MMX enabled " - "changes the ABI"); - } if (cum->mmx_nregs) return gen_reg_or_parallel (mode, orig_mode, cum->mmx_regno + FIRST_MMX_REG); @@ -6977,7 +6977,7 @@ /* To simplify the code below, represent vector types with a vector mode even if MMX/SSE are not active. */ if (type && TREE_CODE (type) == VECTOR_TYPE) - mode = type_natural_mode (type, cum); + mode = type_natural_mode (type, cum, false); if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) arg = function_arg_ms_64 (cum, mode, omode, named, bytes); @@ -7235,9 +7235,15 @@ switch (regno) { case AX_REG: + case DX_REG: return true; - - case FIRST_FLOAT_REG: + case DI_REG: + case SI_REG: + return TARGET_64BIT && ix86_abi != MS_ABI; + + /* Complex values are returned in %st(0)/%st(1) pair. */ + case ST0_REG: + case ST1_REG: /* TODO: The function should depend on current function ABI but builtins.c would need updating then. Therefore we use the default ABI. */ @@ -7245,10 +7251,12 @@ return false; return TARGET_FLOAT_RETURNS_IN_80387; - case FIRST_SSE_REG: + /* Complex values are returned in %xmm0/%xmm1 pair. */ + case XMM0_REG: + case XMM1_REG: return TARGET_SSE; - case FIRST_MMX_REG: + case MM0_REG: if (TARGET_MACHO || TARGET_64BIT) return false; return TARGET_MMX; @@ -7420,7 +7428,7 @@ enum machine_mode mode, orig_mode; orig_mode = TYPE_MODE (valtype); - mode = type_natural_mode (valtype, NULL); + mode = type_natural_mode (valtype, NULL, true); return ix86_function_value_1 (valtype, fntype_or_decl, orig_mode, mode); } @@ -7535,7 +7543,7 @@ #ifdef SUBTARGET_RETURN_IN_MEMORY return SUBTARGET_RETURN_IN_MEMORY (type, fntype); #else - const enum machine_mode mode = type_natural_mode (type, NULL); + const enum machine_mode mode = type_natural_mode (type, NULL, true); if (TARGET_64BIT) { @@ -7549,52 +7557,6 @@ #endif } -/* When returning SSE vector types, we have a choice of either - (1) being abi incompatible with a -march switch, or - (2) generating an error. - Given no good solution, I think the safest thing is one warning. - The user won't be able to use -Werror, but.... - - Choose the STRUCT_VALUE_RTX hook because that's (at present) only - called in response to actually generating a caller or callee that - uses such a type. As opposed to TARGET_RETURN_IN_MEMORY, which is called - via aggregate_value_p for general type probing from tree-ssa. */ - -static rtx -ix86_struct_value_rtx (tree type, int incoming ATTRIBUTE_UNUSED) -{ - static bool warnedsse, warnedmmx; - - if (!TARGET_64BIT && type) - { - /* Look at the return type of the function, not the function type. */ - enum machine_mode mode = TYPE_MODE (TREE_TYPE (type)); - - if (!TARGET_SSE && !warnedsse) - { - if (mode == TImode - || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16)) - { - warnedsse = true; - warning (0, "SSE vector return without SSE enabled " - "changes the ABI"); - } - } - - if (!TARGET_MMX && !warnedmmx) - { - if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8) - { - warnedmmx = true; - warning (0, "MMX vector return without MMX enabled " - "changes the ABI"); - } - } - } - - return NULL; -} - /* Create the va_list data type. */ @@ -8019,7 +7981,7 @@ size = int_size_in_bytes (type); rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - nat_mode = type_natural_mode (type, NULL); + nat_mode = type_natural_mode (type, NULL, false); switch (nat_mode) { case V8SFmode: @@ -10560,18 +10522,20 @@ } m->fs.sp_offset += allocate; + /* Use stack_pointer_rtx for relative addressing so that code + works for realigned stack, too. */ if (r10_live && eax_live) { - t = choose_baseaddr (m->fs.sp_offset - allocate); + t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, eax); emit_move_insn (gen_rtx_REG (word_mode, R10_REG), gen_frame_mem (word_mode, t)); - t = choose_baseaddr (m->fs.sp_offset - allocate - UNITS_PER_WORD); + t = plus_constant (Pmode, t, UNITS_PER_WORD); emit_move_insn (gen_rtx_REG (word_mode, AX_REG), gen_frame_mem (word_mode, t)); } else if (eax_live || r10_live) { - t = choose_baseaddr (m->fs.sp_offset - allocate); + t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, eax); emit_move_insn (gen_rtx_REG (word_mode, (eax_live ? AX_REG : R10_REG)), gen_frame_mem (word_mode, t)); @@ -11561,30 +11525,6 @@ } } -/* Determine if op is suitable SUBREG RTX for address. */ - -static bool -ix86_address_subreg_operand (rtx op) -{ - enum machine_mode mode; - - if (!REG_P (op)) - return false; - - mode = GET_MODE (op); - - if (GET_MODE_CLASS (mode) != MODE_INT) - return false; - - /* Don't allow SUBREGs that span more than a word. It can lead to spill - failures when the register is one word out of a two word structure. */ - if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) - return false; - - /* Allow only SUBREGs of non-eliminable hard registers. */ - return register_no_elim_operand (op, mode); -} - /* Extract the parts of an RTL expression that is a valid memory address for an instruction. Return 0 if the structure of the address is grossly off. Return -1 if the address contains ASHIFT, so it is not @@ -11641,7 +11581,7 @@ base = addr; else if (GET_CODE (addr) == SUBREG) { - if (ix86_address_subreg_operand (SUBREG_REG (addr))) + if (REG_P (SUBREG_REG (addr))) base = addr; else return 0; @@ -11705,7 +11645,7 @@ break; case SUBREG: - if (!ix86_address_subreg_operand (SUBREG_REG (op))) + if (!REG_P (SUBREG_REG (op))) return 0; /* FALLTHRU */ @@ -11750,19 +11690,6 @@ scale = 1 << scale; retval = -1; } - else if (CONST_INT_P (addr)) - { - if (!x86_64_immediate_operand (addr, VOIDmode)) - return 0; - - /* Constant addresses are sign extended to 64bit, we have to - prevent addresses from 0x80000000 to 0xffffffff in x32 mode. */ - if (TARGET_X32 - && val_signbit_known_set_p (SImode, INTVAL (addr))) - return 0; - - disp = addr; - } else disp = addr; /* displacement */ @@ -11771,18 +11698,12 @@ if (REG_P (index)) ; else if (GET_CODE (index) == SUBREG - && ix86_address_subreg_operand (SUBREG_REG (index))) + && REG_P (SUBREG_REG (index))) ; else return 0; } -/* Address override works only on the (%reg) part of %fs:(%reg). */ - if (seg != SEG_DEFAULT - && ((base && GET_MODE (base) != word_mode) - || (index && GET_MODE (index) != word_mode))) - return 0; - /* Extract the integral value of scale. */ if (scale_rtx) { @@ -12258,6 +12179,45 @@ return false; } +/* Determine if op is suitable RTX for an address register. + Return naked register if a register or a register subreg is + found, otherwise return NULL_RTX. */ + +static rtx +ix86_validate_address_register (rtx op) +{ + enum machine_mode mode = GET_MODE (op); + + /* Only SImode or DImode registers can form the address. */ + if (mode != SImode && mode != DImode) + return NULL_RTX; + + if (REG_P (op)) + return op; + else if (GET_CODE (op) == SUBREG) + { + rtx reg = SUBREG_REG (op); + + if (!REG_P (reg)) + return NULL_RTX; + + mode = GET_MODE (reg); + + /* Don't allow SUBREGs that span more than a word. It can + lead to spill failures when the register is one word out + of a two word structure. */ + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) + return NULL_RTX; + + /* Allow only SUBREGs of non-eliminable hard registers. */ + if (register_no_elim_operand (reg, mode)) + return reg; + } + + /* Op is not a register. */ + return NULL_RTX; +} + /* Recognizes RTL expressions that are valid memory addresses for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. @@ -12273,6 +12233,7 @@ struct ix86_address parts; rtx base, index, disp; HOST_WIDE_INT scale; + enum ix86_address_seg seg; if (ix86_decompose_address (addr, &parts) <= 0) /* Decomposition failed. */ @@ -12282,21 +12243,14 @@ index = parts.index; disp = parts.disp; scale = parts.scale; + seg = parts.seg; /* Validate base register. */ if (base) { - rtx reg; - - if (REG_P (base)) - reg = base; - else if (GET_CODE (base) == SUBREG && REG_P (SUBREG_REG (base))) - reg = SUBREG_REG (base); - else - /* Base is not a register. */ - return false; + rtx reg = ix86_validate_address_register (base); - if (GET_MODE (base) != SImode && GET_MODE (base) != DImode) + if (reg == NULL_RTX) return false; if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg)) @@ -12308,17 +12262,9 @@ /* Validate index register. */ if (index) { - rtx reg; - - if (REG_P (index)) - reg = index; - else if (GET_CODE (index) == SUBREG && REG_P (SUBREG_REG (index))) - reg = SUBREG_REG (index); - else - /* Index is not a register. */ - return false; + rtx reg = ix86_validate_address_register (index); - if (GET_MODE (index) != SImode && GET_MODE (index) != DImode) + if (reg == NULL_RTX) return false; if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg)) @@ -12332,6 +12278,12 @@ && GET_MODE (base) != GET_MODE (index)) return false; + /* Address override works only on the (%reg) part of %fs:(%reg). */ + if (seg != SEG_DEFAULT + && ((base && GET_MODE (base) != word_mode) + || (index && GET_MODE (index) != word_mode))) + return false; + /* Validate scale factor. */ if (scale != 1) { @@ -12453,6 +12405,12 @@ && !x86_64_immediate_operand (disp, VOIDmode)) /* Displacement is out of range. */ return false; + /* In x32 mode, constant addresses are sign extended to 64bit, so + we have to prevent addresses from 0x80000000 to 0xffffffff. */ + else if (TARGET_X32 && !(index || base) + && CONST_INT_P (disp) + && val_signbit_known_set_p (SImode, INTVAL (disp))) + return false; } /* Everything looks valid. */ @@ -13817,8 +13775,6 @@ Those same assemblers have the same but opposite lossage on cmov. */ if (mode == CCmode) suffix = fp ? "nbe" : "a"; - else if (mode == CCCmode) - suffix = "b"; else gcc_unreachable (); break; @@ -13840,8 +13796,12 @@ } break; case LTU: - gcc_assert (mode == CCmode || mode == CCCmode); - suffix = "b"; + if (mode == CCmode) + suffix = "b"; + else if (mode == CCCmode) + suffix = "c"; + else + gcc_unreachable (); break; case GE: switch (mode) @@ -13861,20 +13821,20 @@ } break; case GEU: - /* ??? As above. */ - gcc_assert (mode == CCmode || mode == CCCmode); - suffix = fp ? "nb" : "ae"; + if (mode == CCmode) + suffix = fp ? "nb" : "ae"; + else if (mode == CCCmode) + suffix = "nc"; + else + gcc_unreachable (); break; case LE: gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode); suffix = "le"; break; case LEU: - /* ??? As above. */ if (mode == CCmode) suffix = "be"; - else if (mode == CCCmode) - suffix = fp ? "nb" : "ae"; else gcc_unreachable (); break; @@ -15340,7 +15300,7 @@ rtx arg = XEXP (XEXP (link, 0), 0); if (ix86_check_avx256_register (&arg, NULL)) - return AVX_U128_ANY; + return AVX_U128_DIRTY; } } @@ -15460,8 +15420,8 @@ { bool avx_reg256_found = false; note_stores (pat, ix86_check_avx256_stores, &avx_reg256_found); - if (!avx_reg256_found) - return AVX_U128_CLEAN; + + return avx_reg256_found ? AVX_U128_DIRTY : AVX_U128_CLEAN; } /* Otherwise, return current mode. Remember that if insn @@ -17350,8 +17310,18 @@ if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun)) return false; - /* Check it is correct to split here. */ - if (!ix86_ok_to_clobber_flags(insn)) + /* The "at least two components" test below might not catch simple + move or zero extension insns if parts.base is non-NULL and parts.disp + is const0_rtx as the only components in the address, e.g. if the + register is %rbp or %r13. As this test is much cheaper and moves or + zero extensions are the common case, do this check first. */ + if (REG_P (operands[1]) + || (SImode_address_operand (operands[1], VOIDmode) + && REG_P (XEXP (operands[1], 0)))) + return false; + + /* Check if it is OK to split here. */ + if (!ix86_ok_to_clobber_flags (insn)) return false; ok = ix86_decompose_address (operands[1], &parts); @@ -18486,12 +18456,7 @@ return CCmode; case GTU: /* CF=0 & ZF=0 */ case LEU: /* CF=1 | ZF=1 */ - /* Detect overflow checks. They need just the carry flag. */ - if (GET_CODE (op0) == MINUS - && rtx_equal_p (op1, XEXP (op0, 0))) - return CCCmode; - else - return CCmode; + return CCmode; /* Codes possibly doable only with sign flag when comparing against zero. */ case GE: /* SF=OF or SF=0 */ @@ -20500,7 +20465,7 @@ return; case V8SFmode: - mask = gen_lowpart (V8SFmode, mask); + mask = gen_lowpart (V8SImode, mask); if (one_operand_shuffle) emit_insn (gen_avx2_permvarv8sf (target, op0, mask)); else @@ -21740,6 +21705,21 @@ return SImode; } +/* Copy the address to a Pmode register. This is used for x32 to + truncate DImode TLS address to a SImode register. */ + +static rtx +ix86_copy_addr_to_reg (rtx addr) +{ + if (GET_MODE (addr) == Pmode) + return copy_addr_to_reg (addr); + else + { + gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode); + return gen_rtx_SUBREG (SImode, copy_to_mode_reg (DImode, addr), 0); + } +} + /* When SRCPTR is non-NULL, output simple loop to move memory pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT specified in bytes. When SRCPTR is NULL, output the @@ -22728,8 +22708,8 @@ gcc_assert (alg != no_stringop); if (!count) count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp); - destreg = copy_addr_to_reg (XEXP (dst, 0)); - srcreg = copy_addr_to_reg (XEXP (src, 0)); + destreg = ix86_copy_addr_to_reg (XEXP (dst, 0)); + srcreg = ix86_copy_addr_to_reg (XEXP (src, 0)); switch (alg) { case libcall: @@ -23119,7 +23099,7 @@ gcc_assert (alg != no_stringop); if (!count) count_exp = copy_to_mode_reg (counter_mode (count_exp), count_exp); - destreg = copy_addr_to_reg (XEXP (dst, 0)); + destreg = ix86_copy_addr_to_reg (XEXP (dst, 0)); switch (alg) { case libcall: @@ -24988,7 +24968,8 @@ int ix86_data_alignment (tree type, int align) { - int max_align = optimize_size ? BITS_PER_WORD : MIN (256, MAX_OFILE_ALIGNMENT); + int max_align + = optimize_size ? BITS_PER_WORD : MIN (256, MAX_OFILE_ALIGNMENT); if (AGGREGATE_TYPE_P (type) && TYPE_SIZE (type) @@ -27984,8 +27965,8 @@ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv8hi3, "__builtin_ia32_vpshlw", IX86_BUILTIN_VPSHLW, UNKNOWN, (int)MULTI_ARG_2_HI }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv16qi3, "__builtin_ia32_vpshlb", IX86_BUILTIN_VPSHLB, UNKNOWN, (int)MULTI_ARG_2_QI }, - { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_2_SF }, - { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_2_DF }, + { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_1_SF }, + { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_1_DF }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv4sf2, "__builtin_ia32_vfrczps", IX86_BUILTIN_VFRCZPS, UNKNOWN, (int)MULTI_ARG_1_SF }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv2df2, "__builtin_ia32_vfrczpd", IX86_BUILTIN_VFRCZPD, UNKNOWN, (int)MULTI_ARG_1_DF }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv8sf2, "__builtin_ia32_vfrczps256", IX86_BUILTIN_VFRCZPS256, UNKNOWN, (int)MULTI_ARG_1_SF2 }, @@ -31245,11 +31226,12 @@ static rtx ix86_expand_special_args_builtin (const struct builtin_description *d, - tree exp, rtx target) + tree exp, rtx target) { tree arg; rtx pat, op; unsigned int i, nargs, arg_adjust, memory; + bool aligned_mem = false; struct { rtx op; @@ -31295,6 +31277,15 @@ nargs = 1; klass = load; memory = 0; + switch (icode) + { + case CODE_FOR_sse4_1_movntdqa: + case CODE_FOR_avx2_movntdqa: + aligned_mem = true; + break; + default: + break; + } break; case VOID_FTYPE_PV2SF_V4SF: case VOID_FTYPE_PV4DI_V4DI: @@ -31312,6 +31303,26 @@ klass = store; /* Reserve memory operand for target. */ memory = ARRAY_SIZE (args); + switch (icode) + { + /* These builtins and instructions require the memory + to be properly aligned. */ + case CODE_FOR_avx_movntv4di: + case CODE_FOR_sse2_movntv2di: + case CODE_FOR_avx_movntv8sf: + case CODE_FOR_sse_movntv4sf: + case CODE_FOR_sse4a_vmmovntv4sf: + case CODE_FOR_avx_movntv4df: + case CODE_FOR_sse2_movntv2df: + case CODE_FOR_sse4a_vmmovntv2df: + case CODE_FOR_sse2_movntidi: + case CODE_FOR_sse_movntq: + case CODE_FOR_sse2_movntisi: + aligned_mem = true; + break; + default: + break; + } break; case V4SF_FTYPE_V4SF_PCV2SF: case V2DF_FTYPE_V2DF_PCDOUBLE: @@ -31368,6 +31379,17 @@ { op = force_reg (Pmode, convert_to_mode (Pmode, op, 1)); target = gen_rtx_MEM (tmode, op); + /* target at this point has just BITS_PER_UNIT MEM_ALIGN + on it. Try to improve it using get_pointer_alignment, + and if the special builtin is one that requires strict + mode alignment, also from it's GET_MODE_ALIGNMENT. + Failure to do so could lead to ix86_legitimate_combined_insn + rejecting all changes to such insns. */ + unsigned int align = get_pointer_alignment (arg); + if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode)) + align = GET_MODE_ALIGNMENT (tmode); + if (MEM_ALIGN (target) < align) + set_mem_align (target, align); } else target = force_reg (tmode, op); @@ -31413,8 +31435,17 @@ /* This must be the memory operand. */ op = force_reg (Pmode, convert_to_mode (Pmode, op, 1)); op = gen_rtx_MEM (mode, op); - gcc_assert (GET_MODE (op) == mode - || GET_MODE (op) == VOIDmode); + /* op at this point has just BITS_PER_UNIT MEM_ALIGN + on it. Try to improve it using get_pointer_alignment, + and if the special builtin is one that requires strict + mode alignment, also from it's GET_MODE_ALIGNMENT. + Failure to do so could lead to ix86_legitimate_combined_insn + rejecting all changes to such insns. */ + unsigned int align = get_pointer_alignment (arg); + if (aligned_mem && align < GET_MODE_ALIGNMENT (mode)) + align = GET_MODE_ALIGNMENT (mode); + if (MEM_ALIGN (op) < align) + set_mem_align (op, align); } else { @@ -32208,7 +32239,9 @@ mode4 = insn_data[icode].operand[5].mode; if (target == NULL_RTX - || GET_MODE (target) != insn_data[icode].operand[0].mode) + || GET_MODE (target) != insn_data[icode].operand[0].mode + || !insn_data[icode].operand[0].predicate (target, + GET_MODE (target))) subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode); else subtarget = target; @@ -33879,10 +33912,10 @@ { /* We implement the move patterns for all vector modes into and out of SSE registers, even when no operation instructions - are available. OImode move is available only when AVX is - enabled. */ - return ((TARGET_AVX && mode == OImode) - || VALID_AVX256_REG_MODE (mode) + are available. OImode and AVX modes are available only when + AVX is enabled. */ + return ((TARGET_AVX + && VALID_AVX256_REG_OR_OI_MODE (mode)) || VALID_SSE_REG_MODE (mode) || VALID_SSE2_REG_MODE (mode) || VALID_MMX_REG_MODE (mode) @@ -35020,7 +35053,7 @@ { tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, fnaddr), UNSPEC_GOTPCREL); tmp = gen_rtx_CONST (Pmode, tmp); - fnaddr = gen_rtx_MEM (Pmode, tmp); + fnaddr = gen_const_mem (Pmode, tmp); } } else @@ -35040,8 +35073,9 @@ output_set_got (tmp, NULL_RTX); fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, fnaddr), UNSPEC_GOT); - fnaddr = gen_rtx_PLUS (Pmode, fnaddr, tmp); - fnaddr = gen_rtx_MEM (Pmode, fnaddr); + fnaddr = gen_rtx_CONST (Pmode, fnaddr); + fnaddr = gen_rtx_PLUS (Pmode, tmp, fnaddr); + fnaddr = gen_const_mem (Pmode, fnaddr); } } @@ -35232,7 +35266,10 @@ The smallest offset in the page INSN can start is the case where START ends on the offset 0. Offset of INSN is then NBYTES - sizeof (INSN). We add p2align to 16byte window with maxskip 15 - NBYTES + sizeof (INSN). - */ + + Don't consider asm goto as jump, while it can contain a jump, it doesn't + have to, control transfer to label(s) can be performed through other + means, and also we estimate minimum length of all asm stmts as 0. */ for (insn = start; insn; insn = NEXT_INSN (insn)) { int min_size; @@ -35260,6 +35297,7 @@ { start = NEXT_INSN (start); if ((JUMP_P (start) + && asm_noperands (PATTERN (start)) < 0 && GET_CODE (PATTERN (start)) != ADDR_VEC && GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC) || CALL_P (start)) @@ -35278,6 +35316,7 @@ fprintf (dump_file, "Insn %i estimated to %i bytes\n", INSN_UID (insn), min_size); if ((JUMP_P (insn) + && asm_noperands (PATTERN (insn)) < 0 && GET_CODE (PATTERN (insn)) != ADDR_VEC && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) || CALL_P (insn)) @@ -35289,6 +35328,7 @@ { start = NEXT_INSN (start); if ((JUMP_P (start) + && asm_noperands (PATTERN (start)) < 0 && GET_CODE (PATTERN (start)) != ADDR_VEC && GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC) || CALL_P (start)) @@ -39371,7 +39411,9 @@ else dfinal.perm[i] = e; } - dfinal.op0 = gen_reg_rtx (dfinal.vmode); + + if (!d->testing_p) + dfinal.op0 = gen_reg_rtx (dfinal.vmode); dfinal.op1 = dfinal.op0; dfinal.one_operand_p = true; dremap.target = dfinal.op0; @@ -39806,6 +39848,9 @@ return false; gcc_assert (!d->one_operand_p); + if (d->testing_p) + return true; + nelt = d->nelt; eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode)); @@ -40005,6 +40050,8 @@ switch (d->vmode) { case V4DFmode: + if (d->testing_p) + break; t1 = gen_reg_rtx (V4DFmode); t2 = gen_reg_rtx (V4DFmode); @@ -40024,6 +40071,8 @@ { int mask = odd ? 0xdd : 0x88; + if (d->testing_p) + break; t1 = gen_reg_rtx (V8SFmode); t2 = gen_reg_rtx (V8SFmode); t3 = gen_reg_rtx (V8SFmode); @@ -40065,6 +40114,8 @@ return expand_vec_perm_pshufb2 (d); else { + if (d->testing_p) + break; /* We need 2*log2(N)-1 operations to achieve odd/even with interleave. */ t1 = gen_reg_rtx (V8HImode); @@ -40086,6 +40137,8 @@ return expand_vec_perm_pshufb2 (d); else { + if (d->testing_p) + break; t1 = gen_reg_rtx (V16QImode); t2 = gen_reg_rtx (V16QImode); t3 = gen_reg_rtx (V16QImode); @@ -40118,6 +40171,9 @@ return expand_vec_perm_even_odd_1 (&d_copy, odd); } + if (d->testing_p) + break; + t1 = gen_reg_rtx (V4DImode); t2 = gen_reg_rtx (V4DImode); @@ -40144,6 +40200,9 @@ return expand_vec_perm_even_odd_1 (&d_copy, odd); } + if (d->testing_p) + break; + t1 = gen_reg_rtx (V8SImode); t2 = gen_reg_rtx (V8SImode); @@ -40236,6 +40295,8 @@ case V16QImode: /* These can be implemented via interleave. We save one insn by stopping once we have promoted to V4SImode and then use pshufd. */ + if (d->testing_p) + return true; do { rtx dest; @@ -42473,8 +42534,6 @@ #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true -#undef TARGET_STRUCT_VALUE_RTX -#define TARGET_STRUCT_VALUE_RTX ix86_struct_value_rtx #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS ix86_setup_incoming_varargs #undef TARGET_MUST_PASS_IN_STACK diff -Naur gcc-4.8.2.orig/gcc/config/i386/i386.h gcc-4.8.2/gcc/config/i386/i386.h --- gcc-4.8.2.orig/gcc/config/i386/i386.h 2013-01-28 20:42:55.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/i386.h 2014-03-30 20:21:40.597594724 +0000 @@ -197,10 +197,10 @@ /* Macros used in the machine description to test the flags. */ -/* configure can arrange to make this 2, to force a 486. */ +/* configure can arrange to change it. */ #ifndef TARGET_CPU_DEFAULT -#define TARGET_CPU_DEFAULT TARGET_CPU_DEFAULT_generic +#define TARGET_CPU_DEFAULT PROCESSOR_GENERIC32 #endif #ifndef TARGET_FPMATH_DEFAULT @@ -591,43 +591,6 @@ /* Target Pragmas. */ #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas () -enum target_cpu_default -{ - TARGET_CPU_DEFAULT_generic = 0, - - TARGET_CPU_DEFAULT_i386, - TARGET_CPU_DEFAULT_i486, - TARGET_CPU_DEFAULT_pentium, - TARGET_CPU_DEFAULT_pentium_mmx, - TARGET_CPU_DEFAULT_pentiumpro, - TARGET_CPU_DEFAULT_pentium2, - TARGET_CPU_DEFAULT_pentium3, - TARGET_CPU_DEFAULT_pentium4, - TARGET_CPU_DEFAULT_pentium_m, - TARGET_CPU_DEFAULT_prescott, - TARGET_CPU_DEFAULT_nocona, - TARGET_CPU_DEFAULT_core2, - TARGET_CPU_DEFAULT_corei7, - TARGET_CPU_DEFAULT_haswell, - TARGET_CPU_DEFAULT_atom, - - TARGET_CPU_DEFAULT_geode, - TARGET_CPU_DEFAULT_k6, - TARGET_CPU_DEFAULT_k6_2, - TARGET_CPU_DEFAULT_k6_3, - TARGET_CPU_DEFAULT_athlon, - TARGET_CPU_DEFAULT_athlon_sse, - TARGET_CPU_DEFAULT_k8, - TARGET_CPU_DEFAULT_amdfam10, - TARGET_CPU_DEFAULT_bdver1, - TARGET_CPU_DEFAULT_bdver2, - TARGET_CPU_DEFAULT_bdver3, - TARGET_CPU_DEFAULT_btver1, - TARGET_CPU_DEFAULT_btver2, - - TARGET_CPU_DEFAULT_max -}; - #ifndef CC1_SPEC #define CC1_SPEC "%(cc1_cpu) " #endif @@ -2089,32 +2052,33 @@ with x86-64 medium memory model */ #define DEFAULT_LARGE_SECTION_THRESHOLD 65536 -/* Which processor to tune code generation for. */ +/* Which processor to tune code generation for. These must be in sync + with processor_target_table in i386.c. */ enum processor_type { - PROCESSOR_I386 = 0, /* 80386 */ + PROCESSOR_GENERIC32 = 0, + PROCESSOR_GENERIC64, + PROCESSOR_I386, /* 80386 */ PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */ PROCESSOR_PENTIUM, PROCESSOR_PENTIUMPRO, - PROCESSOR_GEODE, - PROCESSOR_K6, - PROCESSOR_ATHLON, PROCESSOR_PENTIUM4, - PROCESSOR_K8, PROCESSOR_NOCONA, PROCESSOR_CORE2, PROCESSOR_COREI7, PROCESSOR_HASWELL, - PROCESSOR_GENERIC32, - PROCESSOR_GENERIC64, + PROCESSOR_ATOM, + PROCESSOR_GEODE, + PROCESSOR_K6, + PROCESSOR_ATHLON, + PROCESSOR_K8, PROCESSOR_AMDFAM10, PROCESSOR_BDVER1, PROCESSOR_BDVER2, PROCESSOR_BDVER3, PROCESSOR_BTVER1, PROCESSOR_BTVER2, - PROCESSOR_ATOM, PROCESSOR_max }; diff -Naur gcc-4.8.2.orig/gcc/config/i386/i386.md gcc-4.8.2/gcc/config/i386/i386.md --- gcc-4.8.2.orig/gcc/config/i386/i386.md 2013-08-13 12:45:06.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/i386.md 2014-03-30 20:21:40.597594724 +0000 @@ -363,6 +363,13 @@ (const_string "unknown")] (const_string "integer"))) +;; The minimum required alignment of vector mode memory operands of the SSE +;; (non-VEX/EVEX) instruction in bits, if it is different from +;; GET_MODE_ALIGNMENT of the operand, otherwise 0. If an instruction has +;; multiple alternatives, this should be conservative maximum of those minimum +;; required alignments. +(define_attr "ssememalign" "" (const_int 0)) + ;; The (bounding maximum) length of an instruction immediate. (define_attr "length_immediate" "" (cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave, @@ -1570,7 +1577,7 @@ split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); - operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, + operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (4))); }) @@ -1587,7 +1594,7 @@ split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); - operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, + operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (4))); }) @@ -2715,7 +2722,20 @@ "reload_completed" [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2))) (set (mem:SF (reg:P SP_REG)) (match_dup 1))] - "operands[2] = GEN_INT (-GET_MODE_SIZE (mode));") +{ + rtx op = XEXP (operands[0], 0); + if (GET_CODE (op) == PRE_DEC) + { + gcc_assert (!TARGET_64BIT); + op = GEN_INT (-4); + } + else + { + op = XEXP (XEXP (op, 1), 1); + gcc_assert (CONST_INT_P (op)); + } + operands[2] = op; +}) (define_split [(set (match_operand:SF 0 "push_operand") @@ -5443,6 +5463,12 @@ mode = SImode; ix86_split_lea_for_addr (curr_insn, operands, mode); + + /* Zero-extend return register to DImode for zero-extended addresses. */ + if (mode != mode) + emit_insn (gen_zero_extendsidi2 + (operands[0], gen_lowpart (mode, operands[0]))); + DONE; } [(set_attr "type" "lea") @@ -6589,7 +6615,7 @@ (set_attr "use_carry" "1") (set_attr "mode" "")]) -;; Overflow setting add and subtract instructions +;; Overflow setting add instructions (define_insn "*add3_cconly_overflow" [(set (reg:CCC FLAGS_REG) @@ -6604,43 +6630,31 @@ [(set_attr "type" "alu") (set_attr "mode" "")]) -(define_insn "*sub3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (minus:SWI - (match_operand:SWI 0 "nonimmediate_operand" "m,") - (match_operand:SWI 1 "" ",m")) - (match_dup 0)))] - "" - "cmp{}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "")]) - -(define_insn "*3_cc_overflow" +(define_insn "*add3_cc_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC - (plusminus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (plus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0,0") (match_operand:SWI 2 "" ",m")) (match_dup 1))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") - (plusminus:SWI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (, mode, operands)" - "{}\t{%2, %0|%0, %2}" + (plus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (PLUS, mode, operands)" + "add{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "")]) -(define_insn "*si3_zext_cc_overflow" +(define_insn "*addsi3_zext_cc_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC - (plusminus:SI - (match_operand:SI 1 "nonimmediate_operand" "0") + (plus:SI + (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "x86_64_general_operand" "rme")) (match_dup 1))) (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" - "{l}\t{%2, %k0|%k0, %2}" + (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" + "add{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) @@ -8012,7 +8026,18 @@ (const_int 0))) (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm") (and:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + "TARGET_64BIT + && ix86_match_ccmode + (insn, + /* If we are going to emit andl instead of andq, and the operands[2] + constant might have the SImode sign bit set, make sure the sign + flag isn't tested, because the instruction will set the sign flag + based on bit 31 rather than bit 63. If it isn't CONST_INT, + conservatively assume it might have bit 31 set. */ + (satisfies_constraint_Z (operands[2]) + && (!CONST_INT_P (operands[2]) + || val_signbit_known_set_p (SImode, INTVAL (operands[2])))) + ? CCZmode : CCNOmode) && ix86_binary_operator_ok (AND, DImode, operands)" "@ and{l}\t{%k2, %k0|%k0, %k2} @@ -17569,7 +17594,13 @@ (define_insn "trap" [(trap_if (const_int 1) (const_int 6))] "" - { return ASM_SHORT "0x0b0f"; } +{ +#ifdef HAVE_AS_IX86_UD2 + return "ud2"; +#else + return ASM_SHORT "0x0b0f"; +#endif +} [(set_attr "length" "2")]) (define_expand "prefetch" diff -Naur gcc-4.8.2.orig/gcc/config/i386/sse.md gcc-4.8.2/gcc/config/i386/sse.md --- gcc-4.8.2.orig/gcc/config/i386/sse.md 2013-08-14 14:09:59.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/sse.md 2014-03-30 20:21:40.600927900 +0000 @@ -605,6 +605,7 @@ } [(set_attr "type" "ssemov") (set_attr "movu" "1") + (set_attr "ssememalign" "8") (set_attr "prefix" "maybe_vex") (set (attr "mode") (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") @@ -634,6 +635,7 @@ } [(set_attr "type" "ssemov") (set_attr "movu" "1") + (set_attr "ssememalign" "8") (set_attr "prefix" "maybe_vex") (set (attr "mode") (cond [(ior (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") @@ -663,6 +665,7 @@ } [(set_attr "type" "ssemov") (set_attr "movu" "1") + (set_attr "ssememalign" "8") (set (attr "prefix_data16") (if_then_else (match_test "TARGET_AVX") @@ -696,6 +699,7 @@ } [(set_attr "type" "ssemov") (set_attr "movu" "1") + (set_attr "ssememalign" "8") (set (attr "prefix_data16") (if_then_else (match_test "TARGET_AVX") @@ -721,6 +725,7 @@ "%vlddqu\t{%1, %0|%0, %1}" [(set_attr "type" "ssemov") (set_attr "movu" "1") + (set_attr "ssememalign" "8") (set (attr "prefix_data16") (if_then_else (match_test "TARGET_AVX") @@ -1001,6 +1006,7 @@ vrcpss\t{%1, %2, %0|%0, %2, %1}" [(set_attr "isa" "noavx,avx") (set_attr "type" "sse") + (set_attr "ssememalign" "32") (set_attr "atom_sse_attr" "rcp") (set_attr "btver2_sse_attr" "rcp") (set_attr "prefix" "orig,vex") @@ -1089,6 +1095,7 @@ vrsqrtss\t{%1, %2, %0|%0, %2, %1}" [(set_attr "isa" "noavx,avx") (set_attr "type" "sse") + (set_attr "ssememalign" "32") (set_attr "prefix" "orig,vex") (set_attr "mode" "SF")]) @@ -2844,6 +2851,7 @@ "%vcvtdq2pd\t{%1, %0|%0, %q1}" [(set_attr "type" "ssecvt") (set_attr "prefix" "maybe_vex") + (set_attr "ssememalign" "64") (set_attr "mode" "V2DF")]) (define_insn "avx_cvtpd2dq256" @@ -3572,6 +3580,7 @@ %vmovhps\t{%2, %0|%0, %2}" [(set_attr "isa" "noavx,avx,noavx,avx,*") (set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix" "orig,vex,orig,vex,maybe_vex") (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")]) @@ -3617,6 +3626,7 @@ %vmovlps\t{%2, %H0|%H0, %2}" [(set_attr "isa" "noavx,avx,noavx,avx,*") (set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix" "orig,vex,orig,vex,maybe_vex") (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")]) @@ -3941,6 +3951,7 @@ %vmovhlps\t{%1, %d0|%d0, %1} %vmovlps\t{%H1, %d0|%d0, %H1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix" "maybe_vex") (set_attr "mode" "V2SF,V4SF,V2SF")]) @@ -3980,6 +3991,7 @@ %vmovlps\t{%2, %H0|%H0, %2}" [(set_attr "isa" "noavx,avx,noavx,avx,*") (set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix" "orig,vex,orig,vex,maybe_vex") (set_attr "mode" "V2SF,V2SF,V4SF,V4SF,V2SF")]) @@ -4033,6 +4045,7 @@ %vmovlps\t{%2, %0|%0, %2}" [(set_attr "isa" "noavx,avx,noavx,avx,*") (set_attr "type" "sseshuf,sseshuf,ssemov,ssemov,ssemov") + (set_attr "ssememalign" "64") (set_attr "length_immediate" "1,1,*,*,*") (set_attr "prefix" "orig,vex,orig,vex,maybe_vex") (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")]) @@ -4642,7 +4655,8 @@ vmovlpd\t{%H1, %2, %0|%0, %2, %H1} %vmovhpd\t{%1, %0|%0, %1}" [(set_attr "isa" "noavx,avx,sse3,noavx,avx,*") - (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov") + (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix_data16" "*,*,*,1,*,1") (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex") (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")]) @@ -4744,6 +4758,7 @@ %vmovlpd\t{%2, %H0|%H0, %2}" [(set_attr "isa" "noavx,avx,sse3,noavx,avx,*") (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix_data16" "*,*,*,1,*,1") (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex") (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")]) @@ -4982,6 +4997,7 @@ movhlps\t{%1, %0|%0, %1} movlps\t{%H1, %0|%0, %H1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "mode" "V2SF,V4SF,V2SF")]) ;; Avoid combining registers from different units in a single alternative, @@ -5077,6 +5093,7 @@ #" [(set_attr "isa" "noavx,avx,noavx,avx,*,*,*") (set_attr "type" "ssemov,ssemov,sselog,sselog,ssemov,fmov,imov") + (set_attr "ssememalign" "64") (set_attr "prefix_data16" "1,*,*,*,*,*,*") (set_attr "prefix" "orig,vex,orig,vex,*,*,*") (set_attr "mode" "V1DF,V1DF,V2DF,V2DF,DF,DF,DF")]) @@ -5145,6 +5162,7 @@ (const_string "imov") ] (const_string "ssemov"))) + (set_attr "ssememalign" "64") (set_attr "prefix_data16" "*,1,*,*,*,*,1,*,*,*,*") (set_attr "length_immediate" "*,*,*,*,*,1,*,*,*,*,*") (set_attr "prefix" "maybe_vex,orig,vex,orig,vex,orig,orig,vex,*,*,*") @@ -5189,6 +5207,7 @@ (const_string "1") (const_string "*"))) (set_attr "length_immediate" "*,*,*,*,*,1,*,*,*") + (set_attr "ssememalign" "64") (set_attr "prefix" "orig,vex,orig,vex,maybe_vex,orig,orig,vex,maybe_vex") (set_attr "mode" "DF,DF,V1DF,V1DF,V1DF,V2DF,V1DF,V1DF,V1DF")]) @@ -8736,6 +8755,7 @@ "TARGET_SSE4_1" "%vpmovbw\t{%1, %0|%0, %q1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) @@ -8766,6 +8786,7 @@ "TARGET_SSE4_1" "%vpmovbd\t{%1, %0|%0, %k1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "32") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) @@ -8791,6 +8812,7 @@ "TARGET_SSE4_1" "%vpmovwd\t{%1, %0|%0, %q1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) @@ -8818,6 +8840,7 @@ "TARGET_SSE4_1" "%vpmovbq\t{%1, %0|%0, %w1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "16") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) @@ -8845,6 +8868,7 @@ "TARGET_SSE4_1" "%vpmovwq\t{%1, %0|%0, %k1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "32") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) @@ -8868,6 +8892,7 @@ "TARGET_SSE4_1" "%vpmovdq\t{%1, %0|%0, %q1}" [(set_attr "type" "ssemov") + (set_attr "ssememalign" "64") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) @@ -9151,6 +9176,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "memory" "none,load") (set_attr "mode" "TI")]) @@ -9213,6 +9239,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "memory" "load") (set_attr "mode" "TI")]) @@ -9240,6 +9267,7 @@ (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "btver2_decode" "vector") (set_attr "memory" "none,load") @@ -9267,6 +9295,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "prefix" "maybe_vex") (set_attr "btver2_decode" "vector") @@ -9293,6 +9322,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "memory" "none,load,none,load") (set_attr "btver2_decode" "vector,vector,vector,vector") @@ -9346,6 +9376,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "memory" "none,load") (set_attr "mode" "TI")]) @@ -9399,6 +9430,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "memory" "load") (set_attr "mode" "TI")]) @@ -9421,6 +9453,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "prefix" "maybe_vex") (set_attr "memory" "none,load") @@ -9445,6 +9478,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "prefix" "maybe_vex") (set_attr "memory" "none,load") @@ -9469,6 +9503,7 @@ [(set_attr "type" "sselog") (set_attr "prefix_data16" "1") (set_attr "prefix_extra" "1") + (set_attr "ssememalign" "8") (set_attr "length_immediate" "1") (set_attr "memory" "none,load,none,load") (set_attr "prefix" "maybe_vex") @@ -10213,21 +10248,18 @@ [(set_attr "type" "ssecvt1") (set_attr "mode" "")]) -;; scalar insns (define_expand "xop_vmfrcz2" [(set (match_operand:VF_128 0 "register_operand") (vec_merge:VF_128 (unspec:VF_128 [(match_operand:VF_128 1 "nonimmediate_operand")] UNSPEC_FRCZ) - (match_dup 3) + (match_dup 2) (const_int 1)))] "TARGET_XOP" -{ - operands[3] = CONST0_RTX (mode); -}) + "operands[2] = CONST0_RTX (mode);") -(define_insn "*xop_vmfrcz_" +(define_insn "*xop_vmfrcz2" [(set (match_operand:VF_128 0 "register_operand" "=x") (vec_merge:VF_128 (unspec:VF_128 diff -Naur gcc-4.8.2.orig/gcc/config/i386/t-rtems gcc-4.8.2/gcc/config/i386/t-rtems --- gcc-4.8.2.orig/gcc/config/i386/t-rtems 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/t-rtems 2014-03-30 20:21:40.600927900 +0000 @@ -17,11 +17,10 @@ # . # -MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro \ -msoft-float +MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro msoft-float MULTILIB_DIRNAMES= m486 mpentium mpentiumpro soft-float -MULTILIB_MATCHES = msoft-float=mno-m80387 -MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?mathlon +MULTILIB_MATCHES = msoft-float=mno-80387 +MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?athlon MULTILIB_EXCEPTIONS = \ mtune=pentium/*msoft-float* \ mtune=pentiumpro/*msoft-float* diff -Naur gcc-4.8.2.orig/gcc/config/i386/winnt.c gcc-4.8.2/gcc/config/i386/winnt.c --- gcc-4.8.2.orig/gcc/config/i386/winnt.c 2013-05-10 01:54:06.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/winnt.c 2014-03-30 20:21:40.600927900 +0000 @@ -547,8 +547,9 @@ sets 'discard' characteristic, rather than telling linker to warn of size or content mismatch, so do the same. */ bool discard = (flags & SECTION_CODE) - || lookup_attribute ("selectany", - DECL_ATTRIBUTES (decl)); + || (TREE_CODE (decl) != IDENTIFIER_NODE + && lookup_attribute ("selectany", + DECL_ATTRIBUTES (decl))); fprintf (asm_out_file, "\t.linkonce %s\n", (discard ? "discard" : "same_size")); } diff -Naur gcc-4.8.2.orig/gcc/config/i386/xopintrin.h gcc-4.8.2/gcc/config/i386/xopintrin.h --- gcc-4.8.2.orig/gcc/config/i386/xopintrin.h 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/i386/xopintrin.h 2014-03-30 20:21:40.600927900 +0000 @@ -745,13 +745,17 @@ extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_frcz_ss (__m128 __A, __m128 __B) { - return (__m128) __builtin_ia32_vfrczss ((__v4sf)__A, (__v4sf)__B); + return (__m128) __builtin_ia32_movss ((__v4sf)__A, + (__v4sf) + __builtin_ia32_vfrczss ((__v4sf)__B)); } extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_frcz_sd (__m128d __A, __m128d __B) { - return (__m128d) __builtin_ia32_vfrczsd ((__v2df)__A, (__v2df)__B); + return (__m128d) __builtin_ia32_movsd ((__v2df)__A, + (__v2df) + __builtin_ia32_vfrczsd ((__v2df)__B)); } extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff -Naur gcc-4.8.2.orig/gcc/config/m68k/m68k.c gcc-4.8.2/gcc/config/m68k/m68k.c --- gcc-4.8.2.orig/gcc/config/m68k/m68k.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/m68k/m68k.c 2014-03-30 20:21:40.600927900 +0000 @@ -3325,12 +3325,12 @@ latehalf[1] = adjust_address (operands[1], SImode, 0); } - /* If insn is effectively movd N(sp),-(sp) then we will do the - high word first. We should use the adjusted operand 1 (which is N+4(sp)) - for the low word as well, to compensate for the first decrement of sp. */ + /* If insn is effectively movd N(REG),-(REG) then we will do the high + word first. We should use the adjusted operand 1 (which is N+4(REG)) + for the low word as well, to compensate for the first decrement of + REG. */ if (optype0 == PUSHOP - && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM - && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) + && reg_overlap_mentioned_p (XEXP (XEXP (operands[0], 0), 0), operands[1])) operands[1] = middlehalf[1] = latehalf[1]; /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)), diff -Naur gcc-4.8.2.orig/gcc/config/microblaze/microblaze.c gcc-4.8.2/gcc/config/microblaze/microblaze.c --- gcc-4.8.2.orig/gcc/config/microblaze/microblaze.c 2013-03-14 15:43:23.000000000 +0000 +++ gcc-4.8.2/gcc/config/microblaze/microblaze.c 2014-03-30 20:21:40.600927900 +0000 @@ -1609,21 +1609,28 @@ microblaze_version_to_int (const char *version) { const char *p, *v; - const char *tmpl = "vX.YY.Z"; + const char *tmpl = "vXX.YY.Z"; int iver = 0; p = version; v = tmpl; - while (*v) + while (*p) { if (*v == 'X') { /* Looking for major */ - if (!(*p >= '0' && *p <= '9')) - return -1; - iver += (int) (*p - '0'); - iver *= 10; - } + if (*p == '.') + { + *v++; + } + else + { + if (!(*p >= '0' && *p <= '9')) + return -1; + iver += (int) (*p - '0'); + iver *= 10; + } + } else if (*v == 'Y') { /* Looking for minor */ if (!(*p >= '0' && *p <= '9')) @@ -3064,6 +3071,73 @@ return result; } +static void +microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, + tree function) +{ + rtx this_rtx, insn, funexp; + + reload_completed = 1; + epilogue_completed = 1; + + /* Mark the end of the (empty) prologue. */ + emit_note (NOTE_INSN_PROLOGUE_END); + + /* Find the "this" pointer. If the function returns a structure, + the structure return pointer is in MB_ABI_FIRST_ARG_REGNUM. */ + if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) + this_rtx = gen_rtx_REG (Pmode, (MB_ABI_FIRST_ARG_REGNUM + 1)); + else + this_rtx = gen_rtx_REG (Pmode, MB_ABI_FIRST_ARG_REGNUM); + + /* Apply the constant offset, if required. */ + if (delta) + emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta))); + + /* Apply the offset from the vtable, if required. */ + if (vcall_offset) + { + rtx vcall_offset_rtx = GEN_INT (vcall_offset); + rtx temp1 = gen_rtx_REG (Pmode, MB_ABI_TEMP1_REGNUM); + + emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx)); + + rtx loc = gen_rtx_PLUS (Pmode, temp1, vcall_offset_rtx); + emit_move_insn (temp1, gen_rtx_MEM (Pmode, loc)); + + emit_insn (gen_addsi3 (this_rtx, this_rtx, temp1)); + } + + /* Generate a tail call to the target function. */ + if (!TREE_USED (function)) + { + assemble_external (function); + TREE_USED (function) = 1; + } + + funexp = XEXP (DECL_RTL (function), 0); + rtx temp2 = gen_rtx_REG (Pmode, MB_ABI_TEMP2_REGNUM); + + if (flag_pic) + emit_move_insn (temp2, expand_pic_symbol_ref (Pmode, funexp)); + else + emit_move_insn (temp2, funexp); + + emit_insn (gen_indirect_jump (temp2)); + + /* Run just enough of rest_of_compilation. This sequence was + "borrowed" from rs6000.c. */ + insn = get_insns (); + shorten_branches (insn); + final_start_function (insn, file, 1); + final (insn, file, 1); + final_end_function (); + + reload_completed = 0; + epilogue_completed = 0; +} + bool microblaze_expand_move (enum machine_mode mode, rtx operands[]) { @@ -3234,65 +3308,45 @@ emit_move_insn (mem, fnaddr); } -/* Emit instruction to perform compare. - cmp is (compare_op op0 op1). */ -static rtx -microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code) +/* Generate conditional branch -- first, generate test condition, + second, generate correct branch instruction. */ + +void +microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[]) { - rtx cmp_op0 = XEXP (cmp, 0); - rtx cmp_op1 = XEXP (cmp, 1); + enum rtx_code code = GET_CODE (operands[0]); + rtx cmp_op0 = operands[1]; + rtx cmp_op1 = operands[2]; + rtx label1 = operands[3]; rtx comp_reg = gen_reg_rtx (SImode); - enum rtx_code code = *cmp_code; - + rtx condition; + gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG)); /* If comparing against zero, just test source reg. */ - if (cmp_op1 == const0_rtx) - return cmp_op0; + if (cmp_op1 == const0_rtx) + { + comp_reg = cmp_op0; + condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx); + emit_jump_insn (gen_condjump (condition, label1)); + } - if (code == EQ || code == NE) + else if (code == EQ || code == NE) { /* Use xor for equal/not-equal comparison. */ emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1)); + condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx); + emit_jump_insn (gen_condjump (condition, label1)); } - else if (code == GT || code == GTU || code == LE || code == LEU) - { - /* MicroBlaze compare is not symmetrical. */ - /* Swap argument order. */ - cmp_op1 = force_reg (mode, cmp_op1); - if (code == GT || code == LE) - emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1)); - else - emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1)); - /* Translate test condition. */ - *cmp_code = swap_condition (code); - } - else /* if (code == GE || code == GEU || code == LT || code == LTU) */ + else { + /* Generate compare and branch in single instruction. */ cmp_op1 = force_reg (mode, cmp_op1); - if (code == GE || code == LT) - emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0)); - else - emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0)); + condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1); + emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1)); } - - return comp_reg; } -/* Generate conditional branch -- first, generate test condition, - second, generate correct branch instruction. */ - -void -microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[]) -{ - enum rtx_code code = GET_CODE (operands[0]); - rtx comp; - rtx condition; - - comp = microblaze_emit_compare (mode, operands[0], &code); - condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx); - emit_jump_insn (gen_condjump (condition, operands[3])); -} void microblaze_expand_conditional_branch_sf (rtx operands[]) @@ -3501,6 +3555,12 @@ #undef TARGET_SECONDARY_RELOAD #define TARGET_SECONDARY_RELOAD microblaze_secondary_reload +#undef TARGET_ASM_OUTPUT_MI_THUNK +#define TARGET_ASM_OUTPUT_MI_THUNK microblaze_asm_output_mi_thunk + +#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK +#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true + #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST microblaze_adjust_cost diff -Naur gcc-4.8.2.orig/gcc/config/microblaze/microblaze.h gcc-4.8.2/gcc/config/microblaze/microblaze.h --- gcc-4.8.2.orig/gcc/config/microblaze/microblaze.h 2013-03-14 15:43:23.000000000 +0000 +++ gcc-4.8.2/gcc/config/microblaze/microblaze.h 2014-03-30 20:21:40.600927900 +0000 @@ -213,6 +213,12 @@ #define STRICT_ALIGNMENT 1 #define PCC_BITFIELD_TYPE_MATTERS 1 +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + #define CONSTANT_ALIGNMENT(EXP, ALIGN) \ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ && (ALIGN) < BITS_PER_WORD \ @@ -407,9 +413,6 @@ || GET_MODE (X) == VOIDmode) \ ? (GR_REGS) : (CLASS)))) -#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ - (GET_MODE_CLASS (MODE) == MODE_INT) - /* Stack layout; function entry, exit and calling. */ #define STACK_GROWS_DOWNWARD diff -Naur gcc-4.8.2.orig/gcc/config/microblaze/microblaze.md gcc-4.8.2/gcc/config/microblaze/microblaze.md --- gcc-4.8.2.orig/gcc/config/microblaze/microblaze.md 2013-03-14 15:43:23.000000000 +0000 +++ gcc-4.8.2/gcc/config/microblaze/microblaze.md 2014-03-30 20:21:40.600927900 +0000 @@ -74,7 +74,7 @@ ;; bshift Shift operations (define_attr "type" - "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt" + "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt,trap" (const_string "unknown")) ;; Main data type used by the insn @@ -365,7 +365,8 @@ [(set (match_operand:HI 0 "register_operand" "=r") (bswap:HI (match_operand:HI 1 "register_operand" "r")))] "TARGET_REORDER" - "swaph %0, %1" + "swapb %0, %1 + swaph %0, %0" ) ;;---------------------------------------------------------------- @@ -1118,6 +1119,18 @@ } ) +;;Load and store reverse +(define_insn "movsi4_rev" + [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Q") + (bswap:SI (match_operand:SF 1 "reg_or_mem_operand" "Q,r")))] + "TARGET_REORDER" + "@ + lwr\t%0,%y1,r0 + swr\t%1,%y0,r0" + [(set_attr "type" "load,store") + (set_attr "mode" "SI") + (set_attr "length" "4,4")]) + ;; 32-bit floating point moves (define_expand "movsf" @@ -1472,7 +1485,7 @@ (set_attr "length" "124")] ) -(define_insn "*ashlri_reg" +(define_insn "*ashrsi_reg" [(set (match_operand:SI 0 "register_operand" "=&d") (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] @@ -1561,7 +1574,7 @@ (set_attr "length" "124")] ) -(define_insn "*lshlri_reg" +(define_insn "*lshrsi_reg" [(set (match_operand:SI 0 "register_operand" "=&d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] @@ -1622,34 +1635,12 @@ (set_attr "length" "4")] ) -(define_insn "signed_compare" - [(set (match_operand:SI 0 "register_operand" "=d") - (unspec - [(match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))] - "" - "cmp\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "4")]) - -(define_insn "unsigned_compare" - [(set (match_operand:SI 0 "register_operand" "=d") - (unspec - [(match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))] - "" - "cmpu\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "4")]) - ;;---------------------------------------------------------------- ;; Setting a register from an floating point comparison. ;;---------------------------------------------------------------- (define_insn "cstoresf4" [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator 1 "comparison_operator" + (match_operator:SI 1 "ordered_comparison_operator" [(match_operand:SF 2 "register_operand" "r") (match_operand:SF 3 "register_operand" "r")]))] "TARGET_HARD_FLOAT" @@ -1678,7 +1669,7 @@ (define_expand "cbranchsf4" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(match_operand:SF 1 "register_operand") (match_operand:SF 2 "register_operand")]) (label_ref (match_operand 3 "")) @@ -1717,6 +1708,47 @@ (set_attr "length" "4")] ) +(define_insn "branch_compare" + [(set (pc) + (if_then_else (match_operator:SI 0 "cmp_op" + [(match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d") + ]) + (label_ref (match_operand 3)) + (pc))) + (clobber(reg:SI R_TMP))] + "" + { + operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); + enum rtx_code code = GET_CODE (operands[0]); + + if (code == GT || code == LE) + { + output_asm_insn ("cmp\tr18,%z1,%z2", operands); + code = swap_condition (code); + } + else if (code == GTU || code == LEU) + { + output_asm_insn ("cmpu\tr18,%z1,%z2", operands); + code = swap_condition (code); + } + else if (code == GE || code == LT) + { + output_asm_insn ("cmp\tr18,%z2,%z1", operands); + } + else if (code == GEU || code == LTU) + { + output_asm_insn ("cmpu\tr18,%z2,%z1", operands); + } + + operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx); + return "b%C0i%?\tr18,%3"; + } + [(set_attr "type" "branch") + (set_attr "mode" "none") + (set_attr "length" "12")] +) + ;;---------------------------------------------------------------- ;; Unconditional branches ;;---------------------------------------------------------------- @@ -2201,6 +2233,14 @@ (set_attr "mode" "none") (set_attr "length" "4")]) +;; Trap instruction pattern for __builtin_trap. Same as the glibc ABORT_INSTRUCTION +(define_insn "trap" + [(trap_if (const_int 1) (const_int 0))] + "" + "brki\tr0,-1" + [(set_attr "type" "trap")] +) + ;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference ;; between "mfs" and "addik" instructions. (define_insn "set_got" diff -Naur gcc-4.8.2.orig/gcc/config/microblaze/predicates.md gcc-4.8.2/gcc/config/microblaze/predicates.md --- gcc-4.8.2.orig/gcc/config/microblaze/predicates.md 2013-03-14 15:43:23.000000000 +0000 +++ gcc-4.8.2/gcc/config/microblaze/predicates.md 2014-03-30 20:21:40.604261087 +0000 @@ -85,6 +85,10 @@ (ior (match_operand 0 "const_0_operand") (match_operand 0 "register_operand"))) +(define_predicate "reg_or_mem_operand" + (ior (match_operand 0 "memory_operand") + (match_operand 0 "register_operand"))) + ;; Return if the operand is either the PC or a label_ref. (define_special_predicate "pc_or_label_operand" (ior (match_code "pc,label_ref") @@ -119,3 +123,7 @@ ;; Test for valid PIC call operand (define_predicate "call_insn_plt_operand" (match_test "PLT_ADDR_P (op)")) + +;; Return if the code of this rtx pattern is a comparison. +(define_predicate "cmp_op" + (match_code "gt,ge,gtu,geu,lt,le,ltu,leu")) diff -Naur gcc-4.8.2.orig/gcc/config/mips/driver-native.c gcc-4.8.2/gcc/config/mips/driver-native.c --- gcc-4.8.2.orig/gcc/config/mips/driver-native.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/mips/driver-native.c 2014-03-30 20:21:40.604261087 +0000 @@ -58,11 +58,17 @@ if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0) { if (strstr (buf, "Godson2 V0.2") != NULL - || strstr (buf, "Loongson-2 V0.2") != NULL) + || strstr (buf, "Loongson-2 V0.2") != NULL + || strstr (buf, "Loongson-2E") != NULL) cpu = "loongson2e"; else if (strstr (buf, "Godson2 V0.3") != NULL - || strstr (buf, "Loongson-2 V0.3") != NULL) + || strstr (buf, "Loongson-2 V0.3") != NULL + || strstr (buf, "Loongson-2F") != NULL) cpu = "loongson2f"; + else if (strstr (buf, "Godson3 V0.5") != NULL + || strstr (buf, "Loongson-3 V0.5") != NULL + || strstr (buf, "Loongson-3A") != NULL) + cpu = "loongson3a"; else if (strstr (buf, "SiByte SB1") != NULL) cpu = "sb1"; else if (strstr (buf, "R5000") != NULL) diff -Naur gcc-4.8.2.orig/gcc/config/mips/mips.c gcc-4.8.2/gcc/config/mips/mips.c --- gcc-4.8.2.orig/gcc/config/mips/mips.c 2013-02-25 13:53:16.000000000 +0000 +++ gcc-4.8.2/gcc/config/mips/mips.c 2014-03-30 20:21:40.604261087 +0000 @@ -3560,17 +3560,6 @@ } } -/* Return the cost of an operand X that can be trucated for free. - SPEED says whether we're optimizing for size or speed. */ - -static int -mips_truncated_op_cost (rtx x, bool speed) -{ - if (GET_CODE (x) == TRUNCATE) - x = XEXP (x, 0); - return set_src_cost (x, speed); -} - /* Implement TARGET_RTX_COSTS. */ static bool @@ -3951,13 +3940,12 @@ case ZERO_EXTEND: if (outer_code == SET && ISA_HAS_BADDU + && (GET_CODE (XEXP (x, 0)) == TRUNCATE + || GET_CODE (XEXP (x, 0)) == SUBREG) && GET_MODE (XEXP (x, 0)) == QImode - && GET_CODE (XEXP (x, 0)) == PLUS) + && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS) { - rtx plus = XEXP (x, 0); - *total = (COSTS_N_INSNS (1) - + mips_truncated_op_cost (XEXP (plus, 0), speed) - + mips_truncated_op_cost (XEXP (plus, 1), speed)); + *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed); return true; } *total = mips_zero_extend_cost (mode, XEXP (x, 0)); @@ -8057,7 +8045,7 @@ case 't': { int truth = (code == NE) == (letter == 'T'); - fputc ("zfnt"[truth * 2 + (GET_MODE (op) == CCmode)], file); + fputc ("zfnt"[truth * 2 + ST_REG_P (REGNO (XEXP (op, 0)))], file); } break; diff -Naur gcc-4.8.2.orig/gcc/config/mips/mips.h gcc-4.8.2/gcc/config/mips/mips.h --- gcc-4.8.2.orig/gcc/config/mips/mips.h 2013-02-25 13:53:16.000000000 +0000 +++ gcc-4.8.2/gcc/config/mips/mips.h 2014-03-30 20:21:40.607594317 +0000 @@ -949,6 +949,11 @@ || TARGET_SMARTMIPS) \ && !TARGET_MIPS16) +/* ISA has the WSBH (word swap bytes within halfwords) instruction. + 64-bit targets also provide DSBH and DSHD. */ +#define ISA_HAS_WSBH ((ISA_MIPS32R2 || ISA_MIPS64R2) \ + && !TARGET_MIPS16) + /* ISA has data prefetch instructions. This controls use of 'pref'. */ #define ISA_HAS_PREFETCH ((ISA_MIPS4 \ || TARGET_LOONGSON_2EF \ diff -Naur gcc-4.8.2.orig/gcc/config/mips/mips.md gcc-4.8.2/gcc/config/mips/mips.md --- gcc-4.8.2.orig/gcc/config/mips/mips.md 2013-02-25 13:53:16.000000000 +0000 +++ gcc-4.8.2/gcc/config/mips/mips.md 2014-03-30 20:21:40.607594317 +0000 @@ -73,6 +73,11 @@ UNSPEC_STORE_LEFT UNSPEC_STORE_RIGHT + ;; Integer operations that are too cumbersome to describe directly. + UNSPEC_WSBH + UNSPEC_DSBH + UNSPEC_DSHD + ;; Floating-point moves. UNSPEC_LOAD_LOW UNSPEC_LOAD_HIGH @@ -1294,20 +1299,32 @@ ;; Combiner patterns for unsigned byte-add. -(define_insn "*baddu_si" +(define_insn "*baddu_si_eb" + [(set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI + (subreg:QI + (plus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) 3)))] + "ISA_HAS_BADDU && BYTES_BIG_ENDIAN" + "baddu\\t%0,%1,%2" + [(set_attr "alu_type" "add")]) + +(define_insn "*baddu_si_el" [(set (match_operand:SI 0 "register_operand" "=d") (zero_extend:SI - (plus:QI (match_operand:QI 1 "register_operand" "d") - (match_operand:QI 2 "register_operand" "d"))))] - "ISA_HAS_BADDU" + (subreg:QI + (plus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) 0)))] + "ISA_HAS_BADDU && !BYTES_BIG_ENDIAN" "baddu\\t%0,%1,%2" [(set_attr "alu_type" "add")]) (define_insn "*baddu_di" [(set (match_operand:GPR 0 "register_operand" "=d") (zero_extend:GPR - (plus:QI (truncate:QI (match_operand:DI 1 "register_operand" "d")) - (truncate:QI (match_operand:DI 2 "register_operand" "d")))))] + (truncate:QI + (plus:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "d")))))] "ISA_HAS_BADDU && TARGET_64BIT" "baddu\\t%0,%1,%2" [(set_attr "alu_type" "add")]) @@ -5367,6 +5384,56 @@ } [(set_attr "type" "shift") (set_attr "mode" "")]) + +(define_insn "bswaphi2" + [(set (match_operand:HI 0 "register_operand" "=d") + (bswap:HI (match_operand:HI 1 "register_operand" "d")))] + "ISA_HAS_WSBH" + "wsbh\t%0,%1" + [(set_attr "type" "shift")]) + +(define_insn_and_split "bswapsi2" + [(set (match_operand:SI 0 "register_operand" "=d") + (bswap:SI (match_operand:SI 1 "register_operand" "d")))] + "ISA_HAS_WSBH && ISA_HAS_ROR" + "#" + "" + [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_WSBH)) + (set (match_dup 0) (rotatert:SI (match_dup 0) (const_int 16)))] + "" + [(set_attr "length" "8")]) + +(define_insn_and_split "bswapdi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (bswap:DI (match_operand:DI 1 "register_operand" "d")))] + "TARGET_64BIT && ISA_HAS_WSBH" + "#" + "" + [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_DSBH)) + (set (match_dup 0) (unspec:DI [(match_dup 0)] UNSPEC_DSHD))] + "" + [(set_attr "length" "8")]) + +(define_insn "wsbh" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(match_operand:SI 1 "register_operand" "d")] UNSPEC_WSBH))] + "ISA_HAS_WSBH" + "wsbh\t%0,%1" + [(set_attr "type" "shift")]) + +(define_insn "dsbh" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSBH))] + "TARGET_64BIT && ISA_HAS_WSBH" + "dsbh\t%0,%1" + [(set_attr "type" "shift")]) + +(define_insn "dshd" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSHD))] + "TARGET_64BIT && ISA_HAS_WSBH" + "dshd\t%0,%1" + [(set_attr "type" "shift")]) ;; ;; .................... diff -Naur gcc-4.8.2.orig/gcc/config/pa/pa.c gcc-4.8.2/gcc/config/pa/pa.c --- gcc-4.8.2.orig/gcc/config/pa/pa.c 2013-09-21 00:00:38.000000000 +0000 +++ gcc-4.8.2/gcc/config/pa/pa.c 2014-03-30 20:21:40.607594317 +0000 @@ -912,9 +912,12 @@ legitimize_tls_address (rtx addr) { rtx ret, insn, tmp, t1, t2, tp; - enum tls_model model = SYMBOL_REF_TLS_MODEL (addr); - switch (model) + /* Currently, we can't handle anything but a SYMBOL_REF. */ + if (GET_CODE (addr) != SYMBOL_REF) + return addr; + + switch (SYMBOL_REF_TLS_MODEL (addr)) { case TLS_MODEL_GLOBAL_DYNAMIC: tmp = gen_reg_rtx (Pmode); @@ -1035,7 +1038,7 @@ && !REG_POINTER (XEXP (x, 1))) return gen_rtx_PLUS (Pmode, XEXP (x, 1), XEXP (x, 0)); - if (PA_SYMBOL_REF_TLS_P (x)) + if (pa_tls_referenced_p (x)) return legitimize_tls_address (x); else if (flag_pic) return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode)); @@ -1916,9 +1919,10 @@ not consider them legitimate constants. Loop optimizations can call the emit_move_xxx with one as a source. */ if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) - || function_label_operand (operand1, VOIDmode) || (GET_CODE (operand1) == HIGH - && symbolic_operand (XEXP (operand1, 0), mode))) + && symbolic_operand (XEXP (operand1, 0), mode)) + || function_label_operand (operand1, VOIDmode) + || pa_tls_referenced_p (operand1)) { int ishighonly = 0; @@ -2625,14 +2629,14 @@ if (optype0 == REGOP) latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); else if (optype0 == OFFSOP) - latehalf[0] = adjust_address (operands[0], SImode, 4); + latehalf[0] = adjust_address_nv (operands[0], SImode, 4); else latehalf[0] = operands[0]; if (optype1 == REGOP) latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); else if (optype1 == OFFSOP) - latehalf[1] = adjust_address (operands[1], SImode, 4); + latehalf[1] = adjust_address_nv (operands[1], SImode, 4); else if (optype1 == CNSTOP) split_double (operands[1], &operands[1], &latehalf[1]); else @@ -7539,7 +7543,7 @@ if (!TARGET_LONG_CALLS && distance < MAX_PCREL17F_OFFSET) return 8; - if (TARGET_LONG_ABS_CALL && !flag_pic) + if (!flag_pic) return 12; return 24; @@ -8104,7 +8108,8 @@ return 12; if (TARGET_FAST_INDIRECT_CALLS - || (!TARGET_PORTABLE_RUNTIME + || (!TARGET_LONG_CALLS + && !TARGET_PORTABLE_RUNTIME && ((TARGET_PA_20 && !TARGET_SOM && distance < 7600000) || distance < MAX_PCREL17F_OFFSET))) return 8; @@ -10397,7 +10402,7 @@ /* TLS_MODEL_GLOBAL_DYNAMIC and TLS_MODEL_LOCAL_DYNAMIC are not legitimate constants. The other variants can't be handled by the move patterns after reload starts. */ - if (PA_SYMBOL_REF_TLS_P (x)) + if (pa_tls_referenced_p (x)) return false; if (TARGET_64BIT && GET_CODE (x) == CONST_DOUBLE) @@ -10522,13 +10527,13 @@ /* When INT14_OK_STRICT is false, a secondary reload is needed to adjust the displacement of SImode and DImode floating point - instructions. So, we return false when STRICT is true. We + instructions but this may fail when the register also needs + reloading. So, we return false when STRICT is true. We also reject long displacements for float mode addresses since the majority of accesses will use floating point instructions that don't support 14-bit offsets. */ if (!INT14_OK_STRICT - && reload_in_progress - && strict + && (strict || !(reload_in_progress || reload_completed)) && mode != QImode && mode != HImode) return false; @@ -10588,8 +10593,7 @@ return true; if (!INT14_OK_STRICT - && reload_in_progress - && strict + && (strict || !(reload_in_progress || reload_completed)) && mode != QImode && mode != HImode) return false; diff -Naur gcc-4.8.2.orig/gcc/config/pa/pa.h gcc-4.8.2/gcc/config/pa/pa.h --- gcc-4.8.2.orig/gcc/config/pa/pa.h 2013-02-03 19:52:37.000000000 +0000 +++ gcc-4.8.2/gcc/config/pa/pa.h 2014-03-30 20:21:40.610927611 +0000 @@ -784,9 +784,9 @@ #define MAX_REGS_PER_ADDRESS 2 -/* Non-TLS symbolic references. */ -#define PA_SYMBOL_REF_TLS_P(RTX) \ - (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0) +/* TLS symbolic reference. */ +#define PA_SYMBOL_REF_TLS_P(X) \ + (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (X) != 0) /* Recognize any constant value that is a valid address except for symbolic addresses. We get better CSE by rejecting them @@ -796,7 +796,8 @@ #define CONSTANT_ADDRESS_P(X) \ ((GET_CODE (X) == LABEL_REF \ || (GET_CODE (X) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (X)) \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ + || GET_CODE (X) == CONST_INT \ + || (GET_CODE (X) == CONST && !pa_tls_referenced_p (X)) \ || GET_CODE (X) == HIGH) \ && (reload_in_progress || reload_completed \ || ! pa_symbolic_expression_p (X))) diff -Naur gcc-4.8.2.orig/gcc/config/rs6000/rs6000.c gcc-4.8.2/gcc/config/rs6000/rs6000.c --- gcc-4.8.2.orig/gcc/config/rs6000/rs6000.c 2013-09-23 14:19:31.000000000 +0000 +++ gcc-4.8.2/gcc/config/rs6000/rs6000.c 2014-03-30 20:21:40.614260916 +0000 @@ -5428,12 +5428,13 @@ break; case TFmode: - case TDmode: - case TImode: if (TARGET_E500_DOUBLE) return (SPE_CONST_OFFSET_OK (offset) && SPE_CONST_OFFSET_OK (offset + 8)); + /* fall through */ + case TDmode: + case TImode: extra = 8; if (!worst_case) break; diff -Naur gcc-4.8.2.orig/gcc/config/rs6000/rs6000.md gcc-4.8.2/gcc/config/rs6000/rs6000.md --- gcc-4.8.2.orig/gcc/config/rs6000/rs6000.md 2013-09-23 14:27:06.000000000 +0000 +++ gcc-4.8.2/gcc/config/rs6000/rs6000.md 2014-03-30 20:21:40.614260916 +0000 @@ -2412,7 +2412,7 @@ (match_operand:SI 2 "gpc_reg_operand" "r,r")) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r"))] - "" + "TARGET_32BIT" "@ mullw. %3,%1,%2 #" @@ -2425,7 +2425,7 @@ (match_operand:SI 2 "gpc_reg_operand" "")) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "reload_completed" + "TARGET_32BIT && reload_completed" [(set (match_dup 3) (mult:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) @@ -2440,7 +2440,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (mult:SI (match_dup 1) (match_dup 2)))] - "" + "TARGET_32BIT" "@ mullw. %0,%1,%2 #" @@ -2454,7 +2454,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (mult:SI (match_dup 1) (match_dup 2)))] - "reload_completed" + "TARGET_32BIT && reload_completed" [(set (match_dup 0) (mult:SI (match_dup 1) (match_dup 2))) (set (match_dup 3) diff -Naur gcc-4.8.2.orig/gcc/config/s390/htmxlintrin.h gcc-4.8.2/gcc/config/s390/htmxlintrin.h --- gcc-4.8.2.orig/gcc/config/s390/htmxlintrin.h 2013-08-14 19:44:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/s390/htmxlintrin.h 2014-03-30 20:21:40.614260916 +0000 @@ -33,13 +33,20 @@ the IBM XL compiler. For documentation please see the "z/OS XL C/C++ Programming Guide" publically available on the web. */ -extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +/* FIXME: __TM_simple_begin and __TM_begin should be marked + __always_inline__ as well but this currently produces an error + since the tbegin builtins are "returns_twice" and setjmp_call_p + (calls.c) therefore identifies the functions as calling setjmp. + The tree inliner currently refuses to inline functions calling + setjmp. */ + +long __TM_simple_begin () { return __builtin_tbegin_nofloat (0); } -extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +long __TM_begin (void* const tdb) { return __builtin_tbegin_nofloat (tdb); @@ -78,7 +85,7 @@ if (depth != 0) return depth; - if (tdb->format == 0) + if (tdb->format != 1) return 0; return tdb->nesting_depth; } @@ -90,7 +97,7 @@ { struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; - if (tdb->format == 0) + if (tdb->format != 1) return 0; return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE); @@ -101,7 +108,7 @@ { struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; - if (tdb->format == 0) + if (tdb->format != 1) return 0; if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE) @@ -117,7 +124,7 @@ { struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; - return (tdb->format == 0 + return (tdb->format == 1 && (tdb->abort_code == 4 /* unfiltered program interruption */ || tdb->abort_code == 11 /* restricted instruction */)); } @@ -127,7 +134,7 @@ { struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; - return (tdb->format == 0 + return (tdb->format == 1 && (tdb->abort_code == 7 /* fetch overflow */ || tdb->abort_code == 8 /* store overflow */)); } @@ -137,7 +144,7 @@ { struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; - return tdb->format == 0 && tdb->abort_code == 13; /* depth exceeded */ + return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */ } extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) @@ -145,7 +152,7 @@ { struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; - return (tdb->format == 0 + return (tdb->format == 1 && (tdb->abort_code == 9 /* fetch conflict */ || tdb->abort_code == 10 /* store conflict */)); } diff -Naur gcc-4.8.2.orig/gcc/config/s390/s390-protos.h gcc-4.8.2/gcc/config/s390/s390-protos.h --- gcc-4.8.2.orig/gcc/config/s390/s390-protos.h 2013-08-02 15:41:10.000000000 +0000 +++ gcc-4.8.2/gcc/config/s390/s390-protos.h 2014-03-30 20:21:40.617594188 +0000 @@ -110,5 +110,6 @@ extern int s390_branch_condition_mask (rtx); extern int s390_compare_and_branch_condition_mask (rtx); extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT); +extern void s390_asm_output_function_label (FILE *, const char *, tree); #endif /* RTX_CODE */ diff -Naur gcc-4.8.2.orig/gcc/config/s390/s390.c gcc-4.8.2/gcc/config/s390/s390.c --- gcc-4.8.2.orig/gcc/config/s390/s390.c 2013-10-07 07:47:17.000000000 +0000 +++ gcc-4.8.2/gcc/config/s390/s390.c 2014-03-30 20:21:40.617594188 +0000 @@ -407,6 +407,65 @@ bytes on a z10 (or higher) CPU. */ #define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048) +static const int s390_hotpatch_trampoline_halfwords_default = 12; +static const int s390_hotpatch_trampoline_halfwords_max = 1000000; +static int s390_hotpatch_trampoline_halfwords = -1; + +/* Return the argument of the given hotpatch attribute or the default value if + no argument is present. */ + +static inline int +get_hotpatch_attribute (tree hotpatch_attr) +{ + const_tree args; + + args = TREE_VALUE (hotpatch_attr); + + return (args) ? + TREE_INT_CST_LOW (TREE_VALUE (args)): + s390_hotpatch_trampoline_halfwords_default; +} + +/* Check whether the hotpatch attribute is applied to a function and, if it has + an argument, the argument is valid. */ + +static tree +s390_handle_hotpatch_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); + *no_add_attrs = true; + } + else if (args) + { + tree expr = TREE_VALUE (args); + + if (TREE_CODE (expr) != INTEGER_CST + || !INTEGRAL_TYPE_P (TREE_TYPE (expr)) + || TREE_INT_CST_HIGH (expr) != 0 + || TREE_INT_CST_LOW (expr) > (unsigned int) + s390_hotpatch_trampoline_halfwords_max) + { + error ("requested %qE attribute is not a non-negative integer" + " constant or too large (max. %d)", name, + s390_hotpatch_trampoline_halfwords_max); + *no_add_attrs = true; + } + } + + return NULL_TREE; +} + +static const struct attribute_spec s390_attribute_table[] = { + { "hotpatch", 0, 1, true, false, false, s390_handle_hotpatch_attribute, false + }, + /* End element. */ + { NULL, 0, 0, false, false, false, NULL, false } +}; + /* Return the alignment for LABEL. We default to the -falign-labels value except for the literal pool base label. */ int @@ -883,7 +942,8 @@ { /* For CCRAWmode put the required cc mask into the second operand. */ - if (GET_MODE (XVECEXP (*op0, 0, 0)) == CCRAWmode) + if (GET_MODE (XVECEXP (*op0, 0, 0)) == CCRAWmode + && INTVAL (*op1) >= 0 && INTVAL (*op1) <= 3) *op1 = gen_rtx_CONST_INT (VOIDmode, 1 << (3 - INTVAL (*op1))); *op0 = XVECEXP (*op0, 0, 0); *code = new_code; @@ -1594,6 +1654,46 @@ static void s390_option_override (void) { + unsigned int i; + cl_deferred_option *opt; + vec *v = + (vec *) s390_deferred_options; + + if (v) + FOR_EACH_VEC_ELT (*v, i, opt) + { + switch (opt->opt_index) + { + case OPT_mhotpatch: + s390_hotpatch_trampoline_halfwords = (opt->value) ? + s390_hotpatch_trampoline_halfwords_default : -1; + break; + case OPT_mhotpatch_: + { + int val; + + val = integral_argument (opt->arg); + if (val == -1) + { + /* argument is not a plain number */ + error ("argument to %qs should be a non-negative integer", + "-mhotpatch="); + break; + } + else if (val > s390_hotpatch_trampoline_halfwords_max) + { + error ("argument to %qs is too large (max. %d)", + "-mhotpatch=", s390_hotpatch_trampoline_halfwords_max); + break; + } + s390_hotpatch_trampoline_halfwords = val; + break; + } + default: + gcc_unreachable (); + } + } + /* Set up function hooks. */ init_machine_status = s390_init_machine_status; @@ -3015,15 +3115,22 @@ prefer ADDR_REGS. If 'class' is not a superset of ADDR_REGS, e.g. FP_REGS, reject this reload. */ case CONST: - /* A larl operand with odd addend will get fixed via secondary - reload. So don't request it to be pushed into literal - pool. */ + /* Symrefs cannot be pushed into the literal pool with -fPIC + so we *MUST NOT* return NO_REGS for these cases + (s390_cannot_force_const_mem will return true). + + On the other hand we MUST return NO_REGS for symrefs with + invalid addend which might have been pushed to the literal + pool (no -fPIC). Usually we would expect them to be + handled via secondary reload but this does not happen if + they are used as literal pool slot replacement in reload + inheritance (see emit_input_reload_insns). */ if (TARGET_CPU_ZARCH && GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP(op, 0), 0)) == SYMBOL_REF && GET_CODE (XEXP (XEXP(op, 0), 1)) == CONST_INT) { - if (reg_class_subset_p (ADDR_REGS, rclass)) + if (flag_pic && reg_class_subset_p (ADDR_REGS, rclass)) return ADDR_REGS; else return NO_REGS; @@ -5311,6 +5418,101 @@ gcc_unreachable (); } +/* Returns -1 if the function should not be made hotpatchable. Otherwise it + returns a number >= 0 that is the desired size of the hotpatch trampoline + in halfwords. */ + +static int s390_function_num_hotpatch_trampoline_halfwords (tree decl, + bool do_warn) +{ + tree attr; + + if (DECL_DECLARED_INLINE_P (decl) + || DECL_ARTIFICIAL (decl) + || MAIN_NAME_P (DECL_NAME (decl))) + { + /* - Explicitly inlined functions cannot be hotpatched. + - Artificial functions need not be hotpatched. + - Making the main function hotpatchable is useless. */ + return -1; + } + attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl)); + if (attr || s390_hotpatch_trampoline_halfwords >= 0) + { + if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))) + { + if (do_warn) + warning (OPT_Wattributes, "function %qE with the %qs attribute" + " is not hotpatchable", DECL_NAME (decl), "always_inline"); + return -1; + } + else + { + return (attr) ? + get_hotpatch_attribute (attr) : s390_hotpatch_trampoline_halfwords; + } + } + + return -1; +} + +/* Hook to determine if one function can safely inline another. */ + +static bool +s390_can_inline_p (tree caller, tree callee) +{ + if (s390_function_num_hotpatch_trampoline_halfwords (callee, false) >= 0) + return false; + + return default_target_can_inline_p (caller, callee); +} + +/* Write the extra assembler code needed to declare a function properly. */ + +void +s390_asm_output_function_label (FILE *asm_out_file, const char *fname, + tree decl) +{ + int hotpatch_trampoline_halfwords = -1; + + if (decl) + { + hotpatch_trampoline_halfwords = + s390_function_num_hotpatch_trampoline_halfwords (decl, true); + if (hotpatch_trampoline_halfwords >= 0 + && decl_function_context (decl) != NULL_TREE) + { + warning_at (DECL_SOURCE_LOCATION (decl), OPT_mhotpatch, + "hotpatching is not compatible with nested functions"); + hotpatch_trampoline_halfwords = -1; + } + } + + if (hotpatch_trampoline_halfwords > 0) + { + int i; + + /* Add a trampoline code area before the function label and initialize it + with two-byte nop instructions. This area can be overwritten with code + that jumps to a patched version of the function. */ + for (i = 0; i < hotpatch_trampoline_halfwords; i++) + asm_fprintf (asm_out_file, "\tnopr\t%%r7\n"); + /* Note: The function label must be aligned so that (a) the bytes of the + following nop do not cross a cacheline boundary, and (b) a jump address + (eight bytes for 64 bit targets, 4 bytes for 32 bit targets) can be + stored directly before the label without crossing a cacheline + boundary. All this is necessary to make sure the trampoline code can + be changed atomically. */ + } + + ASM_OUTPUT_LABEL (asm_out_file, fname); + + /* Output a four-byte nop if hotpatching is enabled. This can be overwritten + atomically with a relative backwards jump to the trampoline area. */ + if (hotpatch_trampoline_halfwords >= 0) + asm_fprintf (asm_out_file, "\tnop\t0\n"); +} + /* Output machine-dependent UNSPECs occurring in address constant X in assembler syntax to stdio stream FILE. Returns true if the constant X could be recognized, false otherwise. */ @@ -7846,6 +8048,9 @@ { bb = BASIC_BLOCK (bb_index); + if (!bb) + continue; + FOR_BB_INSNS (bb, insn) { rtx ite, cc, pat, target; @@ -7959,7 +8164,10 @@ if (!result) return; - PATTERN (tbegin_insn) = XVECEXP (PATTERN (tbegin_insn), 0, 0); + PATTERN (tbegin_insn) = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, + XVECEXP (PATTERN (tbegin_insn), 0, 0), + XVECEXP (PATTERN (tbegin_insn), 0, 1))); INSN_CODE (tbegin_insn) = -1; df_insn_rescan (tbegin_insn); @@ -9568,61 +9776,47 @@ void s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p) { - const int CC0 = 1 << 3; - const int CC1 = 1 << 2; - const int CC3 = 1 << 0; - rtx abort_label = gen_label_rtx (); - rtx leave_label = gen_label_rtx (); + rtx retry_plus_two = gen_reg_rtx (SImode); rtx retry_reg = gen_reg_rtx (SImode); rtx retry_label = NULL_RTX; - rtx jump; - rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1); if (retry != NULL_RTX) { emit_move_insn (retry_reg, retry); + emit_insn (gen_addsi3 (retry_plus_two, retry_reg, const2_rtx)); + emit_insn (gen_addsi3 (retry_reg, retry_reg, const1_rtx)); retry_label = gen_label_rtx (); emit_label (retry_label); } if (clobber_fprs_p) - emit_insn (gen_tbegin_1 (tdb, - gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK))); + emit_insn (gen_tbegin_1 (gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK), tdb)); else - emit_insn (gen_tbegin_nofloat_1 (tdb, - gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK))); - - jump = s390_emit_jump (abort_label, - gen_rtx_NE (VOIDmode, - gen_rtx_REG (CCRAWmode, CC_REGNUM), - gen_rtx_CONST_INT (VOIDmode, CC0))); + emit_insn (gen_tbegin_nofloat_1 (gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK), + tdb)); - JUMP_LABEL (jump) = abort_label; - LABEL_NUSES (abort_label) = 1; - add_reg_note (jump, REG_BR_PROB, very_unlikely); - - /* Initialize CC return value. */ - emit_move_insn (dest, const0_rtx); - - s390_emit_jump (leave_label, NULL_RTX); - LABEL_NUSES (leave_label) = 1; - emit_barrier (); - - /* Abort handler code. */ - - emit_label (abort_label); + emit_move_insn (dest, gen_rtx_UNSPEC (SImode, + gen_rtvec (1, gen_rtx_REG (CCRAWmode, + CC_REGNUM)), + UNSPEC_CC_TO_INT)); if (retry != NULL_RTX) { + const int CC0 = 1 << 3; + const int CC1 = 1 << 2; + const int CC3 = 1 << 0; + rtx jump; rtx count = gen_reg_rtx (SImode); + rtx leave_label = gen_label_rtx (); + + /* Exit for success and permanent failures. */ jump = s390_emit_jump (leave_label, gen_rtx_EQ (VOIDmode, gen_rtx_REG (CCRAWmode, CC_REGNUM), - gen_rtx_CONST_INT (VOIDmode, CC1 | CC3))); - LABEL_NUSES (leave_label) = 2; - add_reg_note (jump, REG_BR_PROB, very_unlikely); + gen_rtx_CONST_INT (VOIDmode, CC0 | CC1 | CC3))); + LABEL_NUSES (leave_label) = 1; /* CC2 - transient failure. Perform retry with ppa. */ - emit_move_insn (count, retry); + emit_move_insn (count, retry_plus_two); emit_insn (gen_subsi3 (count, count, retry_reg)); emit_insn (gen_tx_assist (count)); jump = emit_jump_insn (gen_doloop_si64 (retry_label, @@ -9630,13 +9824,8 @@ retry_reg)); JUMP_LABEL (jump) = retry_label; LABEL_NUSES (retry_label) = 1; + emit_label (leave_label); } - - emit_move_insn (dest, gen_rtx_UNSPEC (SImode, - gen_rtvec (1, gen_rtx_REG (CCRAWmode, - CC_REGNUM)), - UNSPEC_CC_TO_INT)); - emit_label (leave_label); } /* Builtins. */ @@ -9674,6 +9863,9 @@ s390_init_builtins (void) { tree ftype, uint64_type; + tree returns_twice_attr = tree_cons (get_identifier ("returns_twice"), + NULL, NULL); + tree noreturn_attr = tree_cons (get_identifier ("noreturn"), NULL, NULL); /* void foo (void) */ ftype = build_function_type_list (void_type_node, NULL_TREE); @@ -9684,17 +9876,17 @@ ftype = build_function_type_list (void_type_node, integer_type_node, NULL_TREE); add_builtin_function ("__builtin_tabort", ftype, - S390_BUILTIN_TABORT, BUILT_IN_MD, NULL, NULL_TREE); + S390_BUILTIN_TABORT, BUILT_IN_MD, NULL, noreturn_attr); add_builtin_function ("__builtin_tx_assist", ftype, S390_BUILTIN_TX_ASSIST, BUILT_IN_MD, NULL, NULL_TREE); /* int foo (void *) */ ftype = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); add_builtin_function ("__builtin_tbegin", ftype, S390_BUILTIN_TBEGIN, - BUILT_IN_MD, NULL, NULL_TREE); + BUILT_IN_MD, NULL, returns_twice_attr); add_builtin_function ("__builtin_tbegin_nofloat", ftype, S390_BUILTIN_TBEGIN_NOFLOAT, - BUILT_IN_MD, NULL, NULL_TREE); + BUILT_IN_MD, NULL, returns_twice_attr); /* int foo (void *, int) */ ftype = build_function_type_list (integer_type_node, ptr_type_node, @@ -9702,11 +9894,11 @@ add_builtin_function ("__builtin_tbegin_retry", ftype, S390_BUILTIN_TBEGIN_RETRY, BUILT_IN_MD, - NULL, NULL_TREE); + NULL, returns_twice_attr); add_builtin_function ("__builtin_tbegin_retry_nofloat", ftype, S390_BUILTIN_TBEGIN_RETRY_NOFLOAT, BUILT_IN_MD, - NULL, NULL_TREE); + NULL, returns_twice_attr); /* int foo (void) */ ftype = build_function_type_list (integer_type_node, NULL_TREE); @@ -11622,6 +11814,12 @@ #undef TARGET_CANONICALIZE_COMPARISON #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE s390_attribute_table + +#undef TARGET_CAN_INLINE_P +#define TARGET_CAN_INLINE_P s390_can_inline_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-s390.h" diff -Naur gcc-4.8.2.orig/gcc/config/s390/s390.h gcc-4.8.2/gcc/config/s390/s390.h --- gcc-4.8.2.orig/gcc/config/s390/s390.h 2013-08-02 15:41:10.000000000 +0000 +++ gcc-4.8.2/gcc/config/s390/s390.h 2014-03-30 20:21:40.617594188 +0000 @@ -217,7 +217,7 @@ #define STACK_BOUNDARY 64 /* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 32 +#define FUNCTION_BOUNDARY 64 /* There is no point aligning anything to a rounder boundary than this. */ #define BIGGEST_ALIGNMENT 64 @@ -878,6 +878,9 @@ fputc ('\n', (FILE)); \ } while (0) +#undef ASM_OUTPUT_FUNCTION_LABEL +#define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \ + s390_asm_output_function_label (FILE, NAME, DECL) /* Miscellaneous parameters. */ diff -Naur gcc-4.8.2.orig/gcc/config/s390/s390.md gcc-4.8.2/gcc/config/s390/s390.md --- gcc-4.8.2.orig/gcc/config/s390/s390.md 2013-10-07 07:45:12.000000000 +0000 +++ gcc-4.8.2/gcc/config/s390/s390.md 2014-03-30 20:21:40.617594188 +0000 @@ -147,6 +147,7 @@ ; Transactional Execution support UNSPECV_TBEGIN + UNSPECV_TBEGIN_TDB UNSPECV_TBEGINC UNSPECV_TEND UNSPECV_TABORT @@ -9896,9 +9897,10 @@ (define_insn "tbegin_1" [(set (reg:CCRAW CC_REGNUM) - (unspec_volatile:CCRAW [(match_operand:BLK 0 "memory_operand" "=Q") - (match_operand 1 "const_int_operand" " D")] + (unspec_volatile:CCRAW [(match_operand 0 "const_int_operand" "D")] UNSPECV_TBEGIN)) + (set (match_operand:BLK 1 "memory_operand" "=Q") + (unspec_volatile:BLK [(match_dup 0)] UNSPECV_TBEGIN_TDB)) (clobber (reg:DF 16)) (clobber (reg:DF 17)) (clobber (reg:DF 18)) @@ -9917,18 +9919,19 @@ (clobber (reg:DF 31))] ; CONST_OK_FOR_CONSTRAINT_P does not work with D constraint since D is ; not supposed to be used for immediates (see genpreds.c). - "TARGET_HTM && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0xffff" - "tbegin\t%0,%x1" + "TARGET_HTM && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 0xffff" + "tbegin\t%1,%x0" [(set_attr "op_type" "SIL")]) ; Same as above but without the FPR clobbers (define_insn "tbegin_nofloat_1" [(set (reg:CCRAW CC_REGNUM) - (unspec_volatile:CCRAW [(match_operand:BLK 0 "memory_operand" "=Q") - (match_operand 1 "const_int_operand" " D")] - UNSPECV_TBEGIN))] - "TARGET_HTM && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0xffff" - "tbegin\t%0,%x1" + (unspec_volatile:CCRAW [(match_operand 0 "const_int_operand" "D")] + UNSPECV_TBEGIN)) + (set (match_operand:BLK 1 "memory_operand" "=Q") + (unspec_volatile:BLK [(match_dup 0)] UNSPECV_TBEGIN_TDB))] + "TARGET_HTM && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 0xffff" + "tbegin\t%1,%x0" [(set_attr "op_type" "SIL")]) @@ -10012,15 +10015,12 @@ ; Transaction perform processor assist (define_expand "tx_assist" - [(set (match_dup 1) (const_int 0)) - (unspec_volatile [(match_operand:SI 0 "register_operand" "") - (match_dup 1) + [(unspec_volatile [(match_operand:SI 0 "register_operand" "") + (reg:SI GPR0_REGNUM) (const_int 1)] UNSPECV_PPA)] "TARGET_HTM" -{ - operands[1] = gen_reg_rtx (SImode); -}) + "") (define_insn "*ppa" [(unspec_volatile [(match_operand:SI 0 "register_operand" "d") @@ -10028,5 +10028,5 @@ (match_operand 2 "const_int_operand" "I")] UNSPECV_PPA)] "TARGET_HTM && INTVAL (operands[2]) < 16" - "ppa\t%0,%1,1" + "ppa\t%0,%1,%2" [(set_attr "op_type" "RRF")]) diff -Naur gcc-4.8.2.orig/gcc/config/s390/s390.opt gcc-4.8.2/gcc/config/s390/s390.opt --- gcc-4.8.2.orig/gcc/config/s390/s390.opt 2013-08-02 15:41:10.000000000 +0000 +++ gcc-4.8.2/gcc/config/s390/s390.opt 2014-03-30 20:21:40.617594188 +0000 @@ -96,6 +96,14 @@ Target Report RejectNegative Negative(msoft-float) InverseMask(SOFT_FLOAT, HARD_FLOAT) Enable hardware floating point +mhotpatch +Target Report Var(s390_deferred_options) Defer +Prepend the function label with 12 two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching. + +mhotpatch= +Target RejectNegative Report Joined Var(s390_deferred_options) Defer +Prepend the function label with the given number of two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching. + mlong-double-128 Target Report RejectNegative Negative(mlong-double-64) Mask(LONG_DOUBLE_128) Use 128-bit long double diff -Naur gcc-4.8.2.orig/gcc/config/sh/constraints.md gcc-4.8.2/gcc/config/sh/constraints.md --- gcc-4.8.2.orig/gcc/config/sh/constraints.md 2013-02-03 20:06:01.000000000 +0000 +++ gcc-4.8.2/gcc/config/sh/constraints.md 2014-03-30 20:21:40.617594188 +0000 @@ -221,6 +221,7 @@ (define_constraint "Q" "A pc relative load operand." (and (match_code "mem") + (match_test "GET_MODE (op) != QImode") (match_test "IS_PC_RELATIVE_LOAD_ADDR_P (XEXP (op, 0))"))) (define_constraint "Bsc" @@ -295,13 +296,15 @@ (define_memory_constraint "Sdd" "A memory reference that uses displacement addressing." - (and (match_test "MEM_P (op) && GET_CODE (XEXP (op, 0)) == PLUS") + (and (match_code "mem") + (match_test "GET_CODE (XEXP (op, 0)) == PLUS") (match_test "REG_P (XEXP (XEXP (op, 0), 0))") (match_test "CONST_INT_P (XEXP (XEXP (op, 0), 1))"))) (define_memory_constraint "Snd" "A memory reference that excludes displacement addressing." - (match_test "! satisfies_constraint_Sdd (op)")) + (and (match_code "mem") + (match_test "! satisfies_constraint_Sdd (op)"))) (define_memory_constraint "Sbv" "A memory reference, as used in SH2A bclr.b, bset.b, etc." diff -Naur gcc-4.8.2.orig/gcc/config/sh/predicates.md gcc-4.8.2/gcc/config/sh/predicates.md --- gcc-4.8.2.orig/gcc/config/sh/predicates.md 2013-02-03 20:06:01.000000000 +0000 +++ gcc-4.8.2/gcc/config/sh/predicates.md 2014-03-30 20:21:40.620927576 +0000 @@ -389,6 +389,12 @@ XEXP (XEXP (op, 0), 1), TARGET_SH2A, true)"))) +;; Returns true if OP is a displacement address that can fit into a +;; 16 bit (non-SH2A) memory load / store insn. +(define_predicate "short_displacement_mem_operand" + (match_test "sh_disp_addr_displacement (op) + <= sh_max_mov_insn_displacement (GET_MODE (op), false)")) + ;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn. (define_predicate "zero_extend_movu_operand" (and (match_operand 0 "displacement_mem_operand") @@ -413,6 +419,11 @@ if (t_reg_operand (op, mode)) return 0; + /* Disallow PC relative QImode loads, since these is no insn to do that + and an imm8 load should be used instead. */ + if (IS_PC_RELATIVE_LOAD_ADDR_P (op) && GET_MODE (op) == QImode) + return false; + if (MEM_P (op)) { rtx inside = XEXP (op, 0); diff -Naur gcc-4.8.2.orig/gcc/config/sh/sh-protos.h gcc-4.8.2/gcc/config/sh/sh-protos.h --- gcc-4.8.2.orig/gcc/config/sh/sh-protos.h 2013-02-03 20:06:01.000000000 +0000 +++ gcc-4.8.2/gcc/config/sh/sh-protos.h 2014-03-30 20:21:40.624261021 +0000 @@ -159,6 +159,8 @@ extern bool sh_cfun_trap_exit_p (void); extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem); extern int sh_eval_treg_value (rtx op); +extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op); +extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a); /* Result value of sh_find_set_of_reg. */ struct set_of_reg diff -Naur gcc-4.8.2.orig/gcc/config/sh/sh.c gcc-4.8.2/gcc/config/sh/sh.c --- gcc-4.8.2.orig/gcc/config/sh/sh.c 2013-03-13 18:09:10.000000000 +0000 +++ gcc-4.8.2/gcc/config/sh/sh.c 2014-03-30 20:21:40.620927576 +0000 @@ -310,9 +310,7 @@ static void sh_conditional_register_usage (void); static bool sh_legitimate_constant_p (enum machine_mode, rtx); static int mov_insn_size (enum machine_mode, bool); -static int max_mov_insn_displacement (enum machine_mode, bool); static int mov_insn_alignment_mask (enum machine_mode, bool); -static HOST_WIDE_INT disp_addr_displacement (rtx); static bool sequence_insn_p (rtx); static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool); static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&, @@ -3628,8 +3626,8 @@ /* Determine the maximum possible displacement for a move insn for the specified mode. */ -static int -max_mov_insn_displacement (enum machine_mode mode, bool consider_sh2a) +int +sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a) { /* The 4 byte displacement move insns are the same as the 2 byte versions but take a 12 bit displacement. All we need to do is to @@ -3665,8 +3663,8 @@ } /* Return the displacement value of a displacement address. */ -static inline HOST_WIDE_INT -disp_addr_displacement (rtx x) +HOST_WIDE_INT +sh_disp_addr_displacement (rtx x) { gcc_assert (satisfies_constraint_Sdd (x)); return INTVAL (XEXP (XEXP (x, 0), 1)); @@ -3703,12 +3701,12 @@ HImode and QImode loads/stores with displacement put pressure on R0 which will most likely require another reg copy. Thus account a higher cost for that. */ - if (offset > 0 && offset <= max_mov_insn_displacement (mode, false)) + if (offset > 0 && offset <= sh_max_mov_insn_displacement (mode, false)) return (mode == HImode || mode == QImode) ? 2 : 1; /* The displacement would fit into a 4 byte move insn (SH2A). */ if (TARGET_SH2A - && offset > 0 && offset <= max_mov_insn_displacement (mode, true)) + && offset > 0 && offset <= sh_max_mov_insn_displacement (mode, true)) return 2; /* The displacement is probably out of range and will require extra @@ -10218,7 +10216,7 @@ else { const HOST_WIDE_INT offset = INTVAL (op); - const int max_disp = max_mov_insn_displacement (mode, consider_sh2a); + const int max_disp = sh_max_mov_insn_displacement (mode, consider_sh2a); const int align_mask = mov_insn_alignment_mask (mode, consider_sh2a); /* If the mode does not support any displacement always return false. @@ -10404,7 +10402,7 @@ effectively disable the small displacement insns. */ const int mode_sz = GET_MODE_SIZE (mode); const int mov_insn_sz = mov_insn_size (mode, false); - const int max_disp = max_mov_insn_displacement (mode, false); + const int max_disp = sh_max_mov_insn_displacement (mode, false); const int max_disp_next = max_disp + mov_insn_sz; HOST_WIDE_INT align_modifier = offset > 127 ? mov_insn_sz : 0; HOST_WIDE_INT offset_adjust; @@ -13165,7 +13163,8 @@ the insns must have the appropriate alternatives. */ if ((mode == QImode || mode == HImode) && rclass != R0_REGS && satisfies_constraint_Sdd (x) - && disp_addr_displacement (x) <= max_mov_insn_displacement (mode, false)) + && sh_disp_addr_displacement (x) + <= sh_max_mov_insn_displacement (mode, false)) return R0_REGS; /* When reload is trying to address a QImode or HImode subreg on the stack, diff -Naur gcc-4.8.2.orig/gcc/config/sh/sh.md gcc-4.8.2/gcc/config/sh/sh.md --- gcc-4.8.2.orig/gcc/config/sh/sh.md 2013-09-13 08:38:22.000000000 +0000 +++ gcc-4.8.2/gcc/config/sh/sh.md 2014-03-30 20:21:40.624261021 +0000 @@ -6831,34 +6831,9 @@ prepare_move_operands (operands, QImode); }) -;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be -;; selected to copy QImode regs. If one of them happens to be allocated -;; on the stack, reload will stick to movqi insn and generate wrong -;; displacement addressing because of the generic m alternatives. -;; With the movqi_reg_reg being specified before movqi it will be initially -;; picked to load/store regs. If the regs regs are on the stack reload -;; try other insns and not stick to movqi_reg_reg, unless there were spilled -;; pseudos in which case 'm' constraints pertain. -;; The same applies to the movhi variants. -;; -;; Notice, that T bit is not allowed as a mov src operand here. This is to -;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which -;; introduces zero extensions after T bit stores and redundant reg copies. -;; -;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a -;; predicate for the mov src operand because reload will have trouble -;; reloading MAC subregs otherwise. For that probably special patterns -;; would be required. -(define_insn "*mov_reg_reg" - [(set (match_operand:QIHI 0 "arith_reg_dest" "=r,m,*z") - (match_operand:QIHI 1 "register_operand" "r,*z,m"))] - "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)" - "@ - mov %1,%0 - mov. %1,%0 - mov. %1,%0" - [(set_attr "type" "move,store,load")]) - +;; Specifying the displacement addressing load / store patterns separately +;; before the generic movqi / movhi pattern allows controlling the order +;; in which load / store insns are selected in a more fine grained way. ;; FIXME: The non-SH2A and SH2A variants should be combined by adding ;; "enabled" attribute as it is done in other targets. (define_insn "*mov_store_mem_disp04" @@ -6908,38 +6883,44 @@ [(set_attr "type" "load") (set_attr "length" "2,2,4")]) -;; The m constraints basically allow any kind of addresses to be used with any -;; source/target register as the other operand. This is not true for -;; displacement addressing modes on anything but SH2A. That's why the -;; specialized load/store insns are specified above. -(define_insn "*movqi" - [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l") - (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))] +;; The order of the constraint alternatives is important here. +;; Q/r has to come first, otherwise PC relative loads might wrongly get +;; placed into delay slots. Since there is no QImode PC relative load, the +;; Q constraint and general_movsrc_operand will reject it for QImode. +;; The Snd alternatives should come before Sdd in order to avoid a preference +;; of using r0 als the register operand for addressing modes other than +;; displacement addressing. +;; The Sdd alternatives allow only r0 as register operand, even though on +;; SH2A any register could be allowed by switching to a 32 bit insn. +;; Generally sticking to the r0 is preferrable, since it generates smaller +;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A. +(define_insn "*mov" + [(set (match_operand:QIHI 0 "general_movdst_operand" + "=r,r,r,Snd,r, Sdd,z, r,l") + (match_operand:QIHI 1 "general_movsrc_operand" + "Q,r,i,r, Snd,z, Sdd,l,r"))] "TARGET_SH1 - && (arith_reg_operand (operands[0], QImode) - || arith_reg_operand (operands[1], QImode))" + && (arith_reg_operand (operands[0], mode) + || arith_reg_operand (operands[1], mode))" "@ + mov. %1,%0 mov %1,%0 - mov.b %1,%0 - mov.b %1,%0 - sts %1,%0 - lds %1,%0" - [(set_attr "type" "movi8,load,store,prget,prset")]) - -(define_insn "*movhi" - [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l") - (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))] - "TARGET_SH1 - && (arith_reg_operand (operands[0], HImode) - || arith_reg_operand (operands[1], HImode))" - "@ - mov.w %1,%0 mov %1,%0 - mov.w %1,%0 - mov.w %1,%0 + mov. %1,%0 + mov. %1,%0 + mov. %1,%0 + mov. %1,%0 sts %1,%0 lds %1,%0" - [(set_attr "type" "pcload,movi8,load,store,prget,prset")]) + [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset") + (set (attr "length") + (cond [(and (match_operand 0 "displacement_mem_operand") + (not (match_operand 0 "short_displacement_mem_operand"))) + (const_int 4) + (and (match_operand 1 "displacement_mem_operand") + (not (match_operand 1 "short_displacement_mem_operand"))) + (const_int 4)] + (const_int 2)))]) (define_insn "*movqi_media" [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") @@ -8427,11 +8408,9 @@ while (true) { - /* It's not safe to go beyond the current basic block after reload. */ set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn, - reload_completed - ? prev_nonnote_insn_bb - : prev_nonnote_insn); + prev_nonnote_insn); + if (s1.set_src == NULL_RTX) break; @@ -8449,15 +8428,25 @@ continue; } - /* It's only safe to remove the testing insn if the T bit is not - modified between the testing insn and the insn that stores the - T bit. Notice that some T bit stores such as negc also modify - the T bit. */ - if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn) - || modified_in_p (get_t_reg_rtx (), s1.insn)) - operands[2] = NULL_RTX; + /* It's only safe to remove the testing insn if the T bit is not + modified between the testing insn and the insn that stores the + T bit. Notice that some T bit stores such as negc also modify + the T bit. */ + if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn) + || modified_in_p (get_t_reg_rtx (), s1.insn) + || !no_labels_between_p (s1.insn, testing_insn)) + operands[2] = NULL_RTX; + else + { + /* If the insn that sets the tested reg has a REG_DEAD note on + the T bit remove that note since we're extending the usage + of the T bit. */ + rtx n = find_regno_note (s1.insn, REG_DEAD, T_REG); + if (n != NULL_RTX) + remove_note (s1.insn, n); + } - break; + break; } if (operands[2] == NULL_RTX) diff -Naur gcc-4.8.2.orig/gcc/config/sh/sh.opt gcc-4.8.2/gcc/config/sh/sh.opt --- gcc-4.8.2.orig/gcc/config/sh/sh.opt 2013-03-13 18:09:10.000000000 +0000 +++ gcc-4.8.2/gcc/config/sh/sh.opt 2014-03-30 20:21:40.624261021 +0000 @@ -21,7 +21,7 @@ ;; Used for various architecture options. Mask(SH_E) -;; Set if the default precision of th FPU is single. +;; Set if the default precision of the FPU is single. Mask(FPU_SINGLE) ;; Set if the a double-precision FPU is present but is restricted to diff -Naur gcc-4.8.2.orig/gcc/config/sparc/leon.md gcc-4.8.2/gcc/config/sparc/leon.md --- gcc-4.8.2.orig/gcc/config/sparc/leon.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/leon.md 2014-03-30 20:21:40.624261021 +0000 @@ -17,40 +17,48 @@ ;; along with GCC; see the file COPYING3. If not see ;; . +;; Leon is a single-issue processor. (define_automaton "leon") -(define_cpu_unit "leon_memory, leon_fpalu" "leon") -(define_cpu_unit "leon_fpmds" "leon") -(define_cpu_unit "write_buf" "leon") +(define_cpu_unit "leon_memory" "leon") (define_insn_reservation "leon_load" 1 - (and (eq_attr "cpu" "leon") - (eq_attr "type" "load,sload,fpload")) + (and (eq_attr "cpu" "leon") (eq_attr "type" "load,sload")) "leon_memory") -(define_insn_reservation "leon_store" 1 - (and (eq_attr "cpu" "leon") - (eq_attr "type" "store,fpstore")) - "leon_memory+write_buf") - -(define_insn_reservation "leon_fp_alu" 1 - (and (eq_attr "cpu" "leon") - (eq_attr "type" "fp,fpmove")) - "leon_fpalu, nothing") - -(define_insn_reservation "leon_fp_mult" 1 - (and (eq_attr "cpu" "leon") - (eq_attr "type" "fpmul")) - "leon_fpmds, nothing") - -(define_insn_reservation "leon_fp_div" 16 - (and (eq_attr "cpu" "leon") - (eq_attr "type" "fpdivs,fpdivd")) - "leon_fpmds, nothing*15") - -(define_insn_reservation "leon_fp_sqrt" 23 - (and (eq_attr "cpu" "leon") - (eq_attr "type" "fpsqrts,fpsqrtd")) - "leon_fpmds, nothing*21") +;; Use a double reservation to work around the load pipeline hazard on UT699. +(define_insn_reservation "leon3_load" 1 + (and (eq_attr "cpu" "leon3") (eq_attr "type" "load,sload")) + "leon_memory*2") +(define_insn_reservation "leon_store" 2 + (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "store")) + "leon_memory*2") + +;; This describes Gaisler Research's FPU + +(define_automaton "grfpu") + +(define_cpu_unit "grfpu_alu" "grfpu") +(define_cpu_unit "grfpu_ds" "grfpu") + +(define_insn_reservation "leon_fp_alu" 4 + (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fp,fpcmp,fpmul")) + "grfpu_alu, nothing*3") + +(define_insn_reservation "leon_fp_divs" 16 + (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivs")) + "grfpu_ds*14, nothing*2") + +(define_insn_reservation "leon_fp_divd" 17 + (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivd")) + "grfpu_ds*15, nothing*2") + +(define_insn_reservation "leon_fp_sqrts" 24 + (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrts")) + "grfpu_ds*22, nothing*2") + +(define_insn_reservation "leon_fp_sqrtd" 25 + (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrtd")) + "grfpu_ds*23, nothing*2") diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sparc-opts.h gcc-4.8.2/gcc/config/sparc/sparc-opts.h --- gcc-4.8.2.orig/gcc/config/sparc/sparc-opts.h 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sparc-opts.h 2014-03-30 20:21:40.627594474 +0000 @@ -30,6 +30,7 @@ PROCESSOR_SUPERSPARC, PROCESSOR_HYPERSPARC, PROCESSOR_LEON, + PROCESSOR_LEON3, PROCESSOR_SPARCLITE, PROCESSOR_F930, PROCESSOR_F934, diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sparc-protos.h gcc-4.8.2/gcc/config/sparc/sparc-protos.h --- gcc-4.8.2.orig/gcc/config/sparc/sparc-protos.h 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sparc-protos.h 2014-03-30 20:21:40.627594474 +0000 @@ -84,9 +84,9 @@ extern int mems_ok_for_ldd_peep (rtx, rtx, rtx); extern int empty_delay_slot (rtx); extern int emit_cbcond_nop (rtx); +extern int eligible_for_call_delay (rtx); extern int eligible_for_return_delay (rtx); extern int eligible_for_sibcall_delay (rtx); -extern int tls_call_delay (rtx); extern int emit_move_sequence (rtx, enum machine_mode); extern int fp_sethi_p (rtx); extern int fp_mov_p (rtx); diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sparc.c gcc-4.8.2/gcc/config/sparc/sparc.c --- gcc-4.8.2.orig/gcc/config/sparc/sparc.c 2013-08-02 21:42:26.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sparc.c 2014-03-30 20:21:40.624261021 +0000 @@ -52,6 +52,7 @@ #include "params.h" #include "df.h" #include "opts.h" +#include "tree-pass.h" /* Processor costs */ @@ -226,6 +227,30 @@ }; static const +struct processor_costs leon3_costs = { + COSTS_N_INSNS (1), /* int load */ + COSTS_N_INSNS (1), /* int signed load */ + COSTS_N_INSNS (1), /* int zeroed load */ + COSTS_N_INSNS (1), /* float load */ + COSTS_N_INSNS (1), /* fmov, fneg, fabs */ + COSTS_N_INSNS (1), /* fadd, fsub */ + COSTS_N_INSNS (1), /* fcmp */ + COSTS_N_INSNS (1), /* fmov, fmovr */ + COSTS_N_INSNS (1), /* fmul */ + COSTS_N_INSNS (14), /* fdivs */ + COSTS_N_INSNS (15), /* fdivd */ + COSTS_N_INSNS (22), /* fsqrts */ + COSTS_N_INSNS (23), /* fsqrtd */ + COSTS_N_INSNS (5), /* imul */ + COSTS_N_INSNS (5), /* imulX */ + 0, /* imul bit factor */ + COSTS_N_INSNS (35), /* idiv */ + COSTS_N_INSNS (35), /* idivX */ + COSTS_N_INSNS (1), /* movcc/movr */ + 0, /* shift penalty */ +}; + +static const struct processor_costs sparclet_costs = { COSTS_N_INSNS (3), /* int load */ COSTS_N_INSNS (3), /* int signed load */ @@ -538,7 +563,6 @@ HOST_WIDE_INT, tree); static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT, const_tree); -static void sparc_reorg (void); static struct machine_function * sparc_init_machine_status (void); static bool sparc_cannot_force_const_mem (enum machine_mode, rtx); static rtx sparc_tls_get_addr (void); @@ -680,9 +704,6 @@ #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg - #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS sparc_rtx_costs #undef TARGET_ADDRESS_COST @@ -804,6 +825,306 @@ struct gcc_target targetm = TARGET_INITIALIZER; +/* Return the memory reference contained in X if any, zero otherwise. */ + +static rtx +mem_ref (rtx x) +{ + if (GET_CODE (x) == SIGN_EXTEND || GET_CODE (x) == ZERO_EXTEND) + x = XEXP (x, 0); + + if (MEM_P (x)) + return x; + + return NULL_RTX; +} + +/* We use a machine specific pass to enable workarounds for errata. + We need to have the (essentially) final form of the insn stream in order + to properly detect the various hazards. Therefore, this machine specific + pass runs as late as possible. The pass is inserted in the pass pipeline + at the end of sparc_option_override. */ + +static bool +sparc_gate_work_around_errata (void) +{ + /* The only errata we handle are those of the AT697F and UT699. */ + return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0; +} + +static unsigned int +sparc_do_work_around_errata (void) +{ + rtx insn, next; + + /* Force all instructions to be split into their final form. */ + split_all_insns_noflow (); + + /* Now look for specific patterns in the insn stream. */ + for (insn = get_insns (); insn; insn = next) + { + bool insert_nop = false; + rtx set; + + /* Look into the instruction in a delay slot. */ + if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE) + insn = XVECEXP (PATTERN (insn), 0, 1); + + /* Look for a single-word load into an odd-numbered FP register. */ + if (sparc_fix_at697f + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 + && MEM_P (SET_SRC (set)) + && REG_P (SET_DEST (set)) + && REGNO (SET_DEST (set)) > 31 + && REGNO (SET_DEST (set)) % 2 != 0) + { + /* The wrong dependency is on the enclosing double register. */ + const unsigned int x = REGNO (SET_DEST (set)) - 1; + unsigned int src1, src2, dest; + int code; + + next = next_active_insn (insn); + if (!next) + break; + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + extract_insn (next); + code = INSN_CODE (next); + + switch (code) + { + case CODE_FOR_adddf3: + case CODE_FOR_subdf3: + case CODE_FOR_muldf3: + case CODE_FOR_divdf3: + dest = REGNO (recog_data.operand[0]); + src1 = REGNO (recog_data.operand[1]); + src2 = REGNO (recog_data.operand[2]); + if (src1 != src2) + { + /* Case [1-4]: + ld [address], %fx+1 + FPOPd %f{x,y}, %f{y,x}, %f{x,y} */ + if ((src1 == x || src2 == x) + && (dest == src1 || dest == src2)) + insert_nop = true; + } + else + { + /* Case 5: + ld [address], %fx+1 + FPOPd %fx, %fx, %fx */ + if (src1 == x + && dest == src1 + && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3)) + insert_nop = true; + } + break; + + case CODE_FOR_sqrtdf2: + dest = REGNO (recog_data.operand[0]); + src1 = REGNO (recog_data.operand[1]); + /* Case 6: + ld [address], %fx+1 + fsqrtd %fx, %fx */ + if (src1 == x && dest == src1) + insert_nop = true; + break; + + default: + break; + } + } + + /* Look for a single-word load into an integer register. */ + else if (sparc_fix_ut699 + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) <= 4 + && mem_ref (SET_SRC (set)) != NULL_RTX + && REG_P (SET_DEST (set)) + && REGNO (SET_DEST (set)) < 32) + { + /* There is no problem if the second memory access has a data + dependency on the first single-cycle load. */ + rtx x = SET_DEST (set); + + next = next_active_insn (insn); + if (!next) + break; + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + /* Look for a second memory access to/from an integer register. */ + if ((set = single_set (next)) != NULL_RTX) + { + rtx src = SET_SRC (set); + rtx dest = SET_DEST (set); + rtx mem; + + /* LDD is affected. */ + if ((mem = mem_ref (src)) != NULL_RTX + && REG_P (dest) + && REGNO (dest) < 32 + && !reg_mentioned_p (x, XEXP (mem, 0))) + insert_nop = true; + + /* STD is *not* affected. */ + else if (MEM_P (dest) + && GET_MODE_SIZE (GET_MODE (dest)) <= 4 + && (src == CONST0_RTX (GET_MODE (dest)) + || (REG_P (src) + && REGNO (src) < 32 + && REGNO (src) != REGNO (x))) + && !reg_mentioned_p (x, XEXP (dest, 0))) + insert_nop = true; + } + } + + /* Look for a single-word load/operation into an FP register. */ + else if (sparc_fix_ut699 + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 + && REG_P (SET_DEST (set)) + && REGNO (SET_DEST (set)) > 31) + { + /* Number of instructions in the problematic window. */ + const int n_insns = 4; + /* The problematic combination is with the sibling FP register. */ + const unsigned int x = REGNO (SET_DEST (set)); + const unsigned int y = x ^ 1; + rtx after; + int i; + + next = next_active_insn (insn); + if (!next) + break; + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + /* Look for a second load/operation into the sibling FP register. */ + if (!((set = single_set (next)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 + && REG_P (SET_DEST (set)) + && REGNO (SET_DEST (set)) == y)) + continue; + + /* Look for a (possible) store from the FP register in the next N + instructions, but bail out if it is again modified or if there + is a store from the sibling FP register before this store. */ + for (after = next, i = 0; i < n_insns; i++) + { + bool branch_p; + + after = next_active_insn (after); + if (!after) + break; + + /* This is a branch with an empty delay slot. */ + if (!NONJUMP_INSN_P (after)) + { + if (++i == n_insns) + break; + branch_p = true; + after = NULL_RTX; + } + /* This is a branch with a filled delay slot. */ + else if (GET_CODE (PATTERN (after)) == SEQUENCE) + { + if (++i == n_insns) + break; + branch_p = true; + after = XVECEXP (PATTERN (after), 0, 1); + } + /* This is a regular instruction. */ + else + branch_p = false; + + if (after && (set = single_set (after)) != NULL_RTX) + { + const rtx src = SET_SRC (set); + const rtx dest = SET_DEST (set); + const unsigned int size = GET_MODE_SIZE (GET_MODE (dest)); + + /* If the FP register is again modified before the store, + then the store isn't affected. */ + if (REG_P (dest) + && (REGNO (dest) == x + || (REGNO (dest) == y && size == 8))) + break; + + if (MEM_P (dest) && REG_P (src)) + { + /* If there is a store from the sibling FP register + before the store, then the store is not affected. */ + if (REGNO (src) == y || (REGNO (src) == x && size == 8)) + break; + + /* Otherwise, the store is affected. */ + if (REGNO (src) == x && size == 4) + { + insert_nop = true; + break; + } + } + } + + /* If we have a branch in the first M instructions, then we + cannot see the (M+2)th instruction so we play safe. */ + if (branch_p && i <= (n_insns - 2)) + { + insert_nop = true; + break; + } + } + } + + else + next = NEXT_INSN (insn); + + if (insert_nop) + emit_insn_before (gen_nop (), next); + } + + return 0; +} + +struct rtl_opt_pass pass_work_around_errata = +{ + { + RTL_PASS, + "errata", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + sparc_gate_work_around_errata, /* gate */ + sparc_do_work_around_errata, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_MACH_DEP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_verify_rtl_sharing, /* todo_flags_finish */ + } +}; + +struct register_pass_info insert_pass_work_around_errata = +{ + &pass_work_around_errata.pass, /* pass */ + "dbr", /* reference_pass_name */ + 1, /* ref_pass_instance_number */ + PASS_POS_INSERT_AFTER /* po_op */ +}; + +/* Helpers for TARGET_DEBUG_OPTIONS. */ static void dump_target_flag_bits (const int flags) { @@ -888,6 +1209,7 @@ { TARGET_CPU_supersparc, PROCESSOR_SUPERSPARC }, { TARGET_CPU_hypersparc, PROCESSOR_HYPERSPARC }, { TARGET_CPU_leon, PROCESSOR_LEON }, + { TARGET_CPU_leon3, PROCESSOR_LEON3 }, { TARGET_CPU_sparclite, PROCESSOR_F930 }, { TARGET_CPU_sparclite86x, PROCESSOR_SPARCLITE86X }, { TARGET_CPU_sparclet, PROCESSOR_TSC701 }, @@ -902,7 +1224,7 @@ }; const struct cpu_default *def; /* Table of values for -m{cpu,tune}=. This must match the order of - the PROCESSOR_* enumeration. */ + the enum processor_type in sparc-opts.h. */ static struct cpu_table { const char *const name; const int disable; @@ -914,8 +1236,8 @@ /* TI TMS390Z55 supersparc */ { "supersparc", MASK_ISA, MASK_V8 }, { "hypersparc", MASK_ISA, MASK_V8|MASK_FPU }, - /* LEON */ - { "leon", MASK_ISA, MASK_V8|MASK_FPU }, + { "leon", MASK_ISA, MASK_V8|MASK_LEON|MASK_FPU }, + { "leon3", MASK_ISA, MASK_V8|MASK_LEON3|MASK_FPU }, { "sparclite", MASK_ISA, MASK_SPARCLITE }, /* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */ { "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE }, @@ -1075,6 +1397,9 @@ #ifndef HAVE_AS_SPARC4 & ~MASK_CBCOND #endif +#ifndef HAVE_AS_LEON + & ~(MASK_LEON | MASK_LEON3) +#endif ); /* If -mfpu or -mno-fpu was explicitly used, don't override with @@ -1164,6 +1489,9 @@ case PROCESSOR_LEON: sparc_costs = &leon_costs; break; + case PROCESSOR_LEON3: + sparc_costs = &leon3_costs; + break; case PROCESSOR_SPARCLET: case PROCESSOR_TSC701: sparc_costs = &sparclet_costs; @@ -1200,6 +1528,10 @@ /* Choose the most relaxed model for the processor. */ else if (TARGET_V9) sparc_memory_model = SMM_RMO; + else if (TARGET_LEON3) + sparc_memory_model = SMM_TSO; + else if (TARGET_LEON) + sparc_memory_model = SMM_SC; else if (TARGET_V8) sparc_memory_model = SMM_PSO; else @@ -1241,6 +1573,13 @@ pessimizes for double floating-point registers. */ if (!global_options_set.x_flag_ira_share_save_slots) flag_ira_share_save_slots = 0; + + /* We register a machine specific pass to work around errata, if any. + The pass mut be scheduled as late as possible so that we have the + (essentially) final form of the insn stream to work on. + Registering the pass must be done at start up. It's convenient to + do it here. */ + register_pass (&insert_pass_work_around_errata); } /* Miscellaneous utilities. */ @@ -3090,10 +3429,13 @@ /* Return nonzero if TRIAL can go into the call delay slot. */ int -tls_call_delay (rtx trial) +eligible_for_call_delay (rtx trial) { rtx pat; + if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE) + return 0; + /* Binutils allows call __tls_get_addr, %tgd_call (foo) add %l7, %o0, %o0, %tgd_add (foo) @@ -3175,11 +3517,7 @@ /* If we have the 'return' instruction, anything that does not use local or output registers and can go into a delay slot wins. */ - else if (return_p - && TARGET_V9 - && !epilogue_renumber (&pat, 1) - && get_attr_in_uncond_branch_delay (trial) - == IN_UNCOND_BRANCH_DELAY_TRUE) + else if (return_p && TARGET_V9 && !epilogue_renumber (&pat, 1)) return 1; /* The 'restore src1,src2,dest' pattern for SImode. */ @@ -3222,21 +3560,20 @@ int regno; rtx pat; - if (GET_CODE (trial) != INSN) - return 0; - - if (get_attr_length (trial) != 1) - return 0; - /* If the function uses __builtin_eh_return, the eh_return machinery occupies the delay slot. */ if (crtl->calls_eh_return) return 0; + if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE) + return 0; + /* In the case of a leaf or flat function, anything can go into the slot. */ if (sparc_leaf_function_p || TARGET_FLAT) - return - get_attr_in_uncond_branch_delay (trial) == IN_UNCOND_BRANCH_DELAY_TRUE; + return 1; + + if (!NONJUMP_INSN_P (trial)) + return 0; pat = PATTERN (trial); if (GET_CODE (pat) == PARALLEL) @@ -3256,9 +3593,7 @@ if (regno >= 8 && regno < 24) return 0; } - return !epilogue_renumber (&pat, 1) - && (get_attr_in_uncond_branch_delay (trial) - == IN_UNCOND_BRANCH_DELAY_TRUE); + return !epilogue_renumber (&pat, 1); } if (GET_CODE (pat) != SET) @@ -3278,10 +3613,7 @@ instruction, it can probably go in. But restore will not work with FP_REGS. */ if (! SPARC_INT_REG_P (regno)) - return (TARGET_V9 - && !epilogue_renumber (&pat, 1) - && get_attr_in_uncond_branch_delay (trial) - == IN_UNCOND_BRANCH_DELAY_TRUE); + return TARGET_V9 && !epilogue_renumber (&pat, 1); return eligible_for_restore_insn (trial, true); } @@ -3293,10 +3625,10 @@ { rtx pat; - if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET) + if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE) return 0; - if (get_attr_length (trial) != 1) + if (!NONJUMP_INSN_P (trial)) return 0; pat = PATTERN (trial); @@ -3315,6 +3647,9 @@ return 1; } + if (GET_CODE (pat) != SET) + return 0; + /* Otherwise, only operations which can be done in tandem with a `restore' insn can go into the delay slot. */ if (GET_CODE (SET_DEST (pat)) != REG @@ -10355,7 +10690,8 @@ tmp = e0.add_with_sign (tmp, false, &add1_ovf); if (tmp.is_negative ()) tmp = tmp.neg_with_overflow (&neg2_ovf); - + else + neg2_ovf = false; result = result.add_with_sign (tmp, false, &add2_ovf); overflow |= neg1_ovf | neg2_ovf | add1_ovf | add2_ovf; } @@ -10897,107 +11233,6 @@ return (vcall_offset >= -32768 || ! fixed_regs[5]); } -/* We use the machine specific reorg pass to enable workarounds for errata. */ - -static void -sparc_reorg (void) -{ - rtx insn, next; - - /* The only erratum we handle for now is that of the AT697F processor. */ - if (!sparc_fix_at697f) - return; - - /* We need to have the (essentially) final form of the insn stream in order - to properly detect the various hazards. Run delay slot scheduling. */ - if (optimize > 0 && flag_delayed_branch) - { - cleanup_barriers (); - dbr_schedule (get_insns ()); - } - - /* Now look for specific patterns in the insn stream. */ - for (insn = get_insns (); insn; insn = next) - { - bool insert_nop = false; - rtx set; - - /* Look for a single-word load into an odd-numbered FP register. */ - if (NONJUMP_INSN_P (insn) - && (set = single_set (insn)) != NULL_RTX - && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 - && MEM_P (SET_SRC (set)) - && REG_P (SET_DEST (set)) - && REGNO (SET_DEST (set)) > 31 - && REGNO (SET_DEST (set)) % 2 != 0) - { - /* The wrong dependency is on the enclosing double register. */ - unsigned int x = REGNO (SET_DEST (set)) - 1; - unsigned int src1, src2, dest; - int code; - - /* If the insn has a delay slot, then it cannot be problematic. */ - next = next_active_insn (insn); - if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE) - code = -1; - else - { - extract_insn (next); - code = INSN_CODE (next); - } - - switch (code) - { - case CODE_FOR_adddf3: - case CODE_FOR_subdf3: - case CODE_FOR_muldf3: - case CODE_FOR_divdf3: - dest = REGNO (recog_data.operand[0]); - src1 = REGNO (recog_data.operand[1]); - src2 = REGNO (recog_data.operand[2]); - if (src1 != src2) - { - /* Case [1-4]: - ld [address], %fx+1 - FPOPd %f{x,y}, %f{y,x}, %f{x,y} */ - if ((src1 == x || src2 == x) - && (dest == src1 || dest == src2)) - insert_nop = true; - } - else - { - /* Case 5: - ld [address], %fx+1 - FPOPd %fx, %fx, %fx */ - if (src1 == x - && dest == src1 - && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3)) - insert_nop = true; - } - break; - - case CODE_FOR_sqrtdf2: - dest = REGNO (recog_data.operand[0]); - src1 = REGNO (recog_data.operand[1]); - /* Case 6: - ld [address], %fx+1 - fsqrtd %fx, %fx */ - if (src1 == x && dest == src1) - insert_nop = true; - break; - - default: - break; - } - } - else - next = NEXT_INSN (insn); - - if (insert_nop) - emit_insn_after (gen_nop (), insn); - } -} - /* How to allocate a 'struct machine_function'. */ static struct machine_function * diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sparc.h gcc-4.8.2/gcc/config/sparc/sparc.h --- gcc-4.8.2.orig/gcc/config/sparc/sparc.h 2013-04-11 00:59:01.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sparc.h 2014-03-30 20:21:40.627594474 +0000 @@ -136,21 +136,22 @@ #define TARGET_CPU_supersparc 2 #define TARGET_CPU_hypersparc 3 #define TARGET_CPU_leon 4 -#define TARGET_CPU_sparclite 5 -#define TARGET_CPU_f930 5 /* alias */ -#define TARGET_CPU_f934 5 /* alias */ -#define TARGET_CPU_sparclite86x 6 -#define TARGET_CPU_sparclet 7 -#define TARGET_CPU_tsc701 7 /* alias */ -#define TARGET_CPU_v9 8 /* generic v9 implementation */ -#define TARGET_CPU_sparcv9 8 /* alias */ -#define TARGET_CPU_sparc64 8 /* alias */ -#define TARGET_CPU_ultrasparc 9 -#define TARGET_CPU_ultrasparc3 10 -#define TARGET_CPU_niagara 11 -#define TARGET_CPU_niagara2 12 -#define TARGET_CPU_niagara3 13 -#define TARGET_CPU_niagara4 14 +#define TARGET_CPU_leon3 5 +#define TARGET_CPU_sparclite 6 +#define TARGET_CPU_f930 6 /* alias */ +#define TARGET_CPU_f934 6 /* alias */ +#define TARGET_CPU_sparclite86x 7 +#define TARGET_CPU_sparclet 8 +#define TARGET_CPU_tsc701 8 /* alias */ +#define TARGET_CPU_v9 9 /* generic v9 implementation */ +#define TARGET_CPU_sparcv9 9 /* alias */ +#define TARGET_CPU_sparc64 9 /* alias */ +#define TARGET_CPU_ultrasparc 10 +#define TARGET_CPU_ultrasparc3 11 +#define TARGET_CPU_niagara 12 +#define TARGET_CPU_niagara2 13 +#define TARGET_CPU_niagara3 14 +#define TARGET_CPU_niagara4 15 #if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \ @@ -232,9 +233,10 @@ #define ASM_CPU32_DEFAULT_SPEC "" #endif -#if TARGET_CPU_DEFAULT == TARGET_CPU_leon +#if TARGET_CPU_DEFAULT == TARGET_CPU_leon \ + || TARGET_CPU_DEFAULT == TARGET_CPU_leon3 #define CPP_CPU32_DEFAULT_SPEC "-D__leon__ -D__sparc_v8__" -#define ASM_CPU32_DEFAULT_SPEC "" +#define ASM_CPU32_DEFAULT_SPEC AS_LEON_FLAG #endif #endif @@ -282,6 +284,7 @@ %{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \ %{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \ %{mcpu=leon:-D__leon__ -D__sparc_v8__} \ +%{mcpu=leon3:-D__leon__ -D__sparc_v8__} \ %{mcpu=v9:-D__sparc_v9__} \ %{mcpu=ultrasparc:-D__sparc_v9__} \ %{mcpu=ultrasparc3:-D__sparc_v9__} \ @@ -329,7 +332,8 @@ %{mcpu=v8:-Av8} \ %{mcpu=supersparc:-Av8} \ %{mcpu=hypersparc:-Av8} \ -%{mcpu=leon:-Av8} \ +%{mcpu=leon:" AS_LEON_FLAG "} \ +%{mcpu=leon3:" AS_LEON_FLAG "} \ %{mv8plus:-Av8plus} \ %{mcpu=v9:-Av9} \ %{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \ @@ -1754,6 +1758,12 @@ #define AS_NIAGARA4_FLAG "-Av9" AS_NIAGARA3_FLAG #endif +#ifdef HAVE_AS_LEON +#define AS_LEON_FLAG "-Aleon" +#else +#define AS_LEON_FLAG "-Av8" +#endif + /* We use gcc _mcount for profiling. */ #define NO_PROFILE_COUNTERS 0 diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sparc.md gcc-4.8.2/gcc/config/sparc/sparc.md --- gcc-4.8.2.orig/gcc/config/sparc/sparc.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sparc.md 2014-03-30 20:21:40.627594474 +0000 @@ -206,7 +206,7 @@ ;; 'f' for all DF/TFmode values, including those that are specific to the v8. ;; Attribute for cpu type. -;; These must match the values for enum processor_type in sparc.h. +;; These must match the values of the enum processor_type in sparc-opts.h. (define_attr "cpu" "v7, cypress, @@ -214,6 +214,7 @@ supersparc, hypersparc, leon, + leon3, sparclite, f930, f934, @@ -284,7 +285,8 @@ (const_string "none")) (define_attr "pic" "false,true" - (symbol_ref "(flag_pic != 0 ? PIC_TRUE : PIC_FALSE)")) + (symbol_ref "(flag_pic != 0 + ? PIC_TRUE : PIC_FALSE)")) (define_attr "calls_alloca" "false,true" (symbol_ref "(cfun->calls_alloca != 0 @@ -306,6 +308,10 @@ (symbol_ref "(TARGET_FLAT != 0 ? FLAT_TRUE : FLAT_FALSE)")) +(define_attr "fix_ut699" "false,true" + (symbol_ref "(sparc_fix_ut699 != 0 + ? FIX_UT699_TRUE : FIX_UT699_FALSE)")) + ;; Length (in # of insns). ;; Beware that setting a length greater or equal to 3 for conditional branches ;; has a side-effect (see output_cbranch and output_v9branch). @@ -420,32 +426,18 @@ [(set_attr "length" "2") (set_attr "type" "multi")]) -;; Attributes for instruction and branch scheduling -(define_attr "tls_call_delay" "false,true" - (symbol_ref "(tls_call_delay (insn) - ? TLS_CALL_DELAY_TRUE : TLS_CALL_DELAY_FALSE)")) - +;; Attributes for branch scheduling (define_attr "in_call_delay" "false,true" - (cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") - (const_string "false") - (eq_attr "type" "load,fpload,store,fpstore") - (if_then_else (eq_attr "length" "1") - (const_string "true") - (const_string "false"))] - (if_then_else (and (eq_attr "length" "1") - (eq_attr "tls_call_delay" "true")) - (const_string "true") - (const_string "false")))) + (symbol_ref "(eligible_for_call_delay (insn) + ? IN_CALL_DELAY_TRUE : IN_CALL_DELAY_FALSE)")) -(define_attr "eligible_for_sibcall_delay" "false,true" +(define_attr "in_sibcall_delay" "false,true" (symbol_ref "(eligible_for_sibcall_delay (insn) - ? ELIGIBLE_FOR_SIBCALL_DELAY_TRUE - : ELIGIBLE_FOR_SIBCALL_DELAY_FALSE)")) + ? IN_SIBCALL_DELAY_TRUE : IN_SIBCALL_DELAY_FALSE)")) -(define_attr "eligible_for_return_delay" "false,true" +(define_attr "in_return_delay" "false,true" (symbol_ref "(eligible_for_return_delay (insn) - ? ELIGIBLE_FOR_RETURN_DELAY_TRUE - : ELIGIBLE_FOR_RETURN_DELAY_FALSE)")) + ? IN_RETURN_DELAY_TRUE : IN_RETURN_DELAY_FALSE)")) ;; ??? !v9: Should implement the notion of predelay slots for floating-point ;; branches. This would allow us to remove the nop always inserted before @@ -460,39 +452,32 @@ ;; because it prevents us from moving back the final store of inner loops. (define_attr "in_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") - (eq_attr "length" "1")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_uncond_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") - (eq_attr "length" "1")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_annul_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") - (eq_attr "length" "1")) - (const_string "true") - (const_string "false"))) + (cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") + (const_string "false") + (and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload")) + (const_string "false") + (and (eq_attr "fix_ut699" "true") + (and (eq_attr "type" "fpload,fp,fpmove,fpmul,fpdivs,fpsqrts") + (eq_attr "fptype" "single"))) + (const_string "false") + (eq_attr "length" "1") + (const_string "true") + ] (const_string "false"))) (define_delay (eq_attr "type" "call") [(eq_attr "in_call_delay" "true") (nil) (nil)]) (define_delay (eq_attr "type" "sibcall") - [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)]) + [(eq_attr "in_sibcall_delay" "true") (nil) (nil)]) + +(define_delay (eq_attr "type" "return") + [(eq_attr "in_return_delay" "true") (nil) (nil)]) (define_delay (eq_attr "type" "branch") - [(eq_attr "in_branch_delay" "true") - (nil) (eq_attr "in_annul_branch_delay" "true")]) + [(eq_attr "in_branch_delay" "true") (nil) (eq_attr "in_branch_delay" "true")]) (define_delay (eq_attr "type" "uncond_branch") - [(eq_attr "in_uncond_branch_delay" "true") - (nil) (nil)]) - -(define_delay (eq_attr "type" "return") - [(eq_attr "eligible_for_return_delay" "true") (nil) (nil)]) + [(eq_attr "in_branch_delay" "true") (nil) (nil)]) ;; Include SPARC DFA schedulers @@ -5548,7 +5533,7 @@ [(set (match_operand:DF 0 "register_operand" "=e") (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f")) (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))] - "(TARGET_V8 || TARGET_V9) && TARGET_FPU" + "(TARGET_V8 || TARGET_V9) && TARGET_FPU && !sparc_fix_ut699" "fsmuld\t%1, %2, %0" [(set_attr "type" "fpmul") (set_attr "fptype" "double")]) @@ -5575,22 +5560,39 @@ (match_operand:TF 2 "register_operand" "e")))] "TARGET_FPU && TARGET_HARD_QUAD" "fdivq\t%1, %2, %0" - [(set_attr "type" "fpdivd")]) + [(set_attr "type" "fpdivs")]) -(define_insn "divdf3" +(define_expand "divdf3" [(set (match_operand:DF 0 "register_operand" "=e") (div:DF (match_operand:DF 1 "register_operand" "e") (match_operand:DF 2 "register_operand" "e")))] "TARGET_FPU" + "") + +(define_insn "*divdf3_nofix" + [(set (match_operand:DF 0 "register_operand" "=e") + (div:DF (match_operand:DF 1 "register_operand" "e") + (match_operand:DF 2 "register_operand" "e")))] + "TARGET_FPU && !sparc_fix_ut699" "fdivd\t%1, %2, %0" [(set_attr "type" "fpdivd") (set_attr "fptype" "double")]) +(define_insn "*divdf3_fix" + [(set (match_operand:DF 0 "register_operand" "=e") + (div:DF (match_operand:DF 1 "register_operand" "e") + (match_operand:DF 2 "register_operand" "e")))] + "TARGET_FPU && sparc_fix_ut699" + "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]" + [(set_attr "type" "fpdivd") + (set_attr "fptype" "double") + (set_attr "length" "2")]) + (define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f") (div:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] - "TARGET_FPU" + "TARGET_FPU && !sparc_fix_ut699" "fdivs\t%1, %2, %0" [(set_attr "type" "fpdivs")]) @@ -5789,20 +5791,35 @@ (sqrt:TF (match_operand:TF 1 "register_operand" "e")))] "TARGET_FPU && TARGET_HARD_QUAD" "fsqrtq\t%1, %0" - [(set_attr "type" "fpsqrtd")]) + [(set_attr "type" "fpsqrts")]) -(define_insn "sqrtdf2" +(define_expand "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=e") (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] "TARGET_FPU" + "") + +(define_insn "*sqrtdf2_nofix" + [(set (match_operand:DF 0 "register_operand" "=e") + (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] + "TARGET_FPU && !sparc_fix_ut699" "fsqrtd\t%1, %0" [(set_attr "type" "fpsqrtd") (set_attr "fptype" "double")]) +(define_insn "*sqrtdf2_fix" + [(set (match_operand:DF 0 "register_operand" "=e") + (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] + "TARGET_FPU && sparc_fix_ut699" + "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]" + [(set_attr "type" "fpsqrtd") + (set_attr "fptype" "double") + (set_attr "length" "2")]) + (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] - "TARGET_FPU" + "TARGET_FPU && !sparc_fix_ut699" "fsqrts\t%1, %0" [(set_attr "type" "fpsqrts")]) diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sparc.opt gcc-4.8.2/gcc/config/sparc/sparc.opt --- gcc-4.8.2.orig/gcc/config/sparc/sparc.opt 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sparc.opt 2014-03-30 20:21:40.627594474 +0000 @@ -146,6 +146,9 @@ Enum(sparc_processor_type) String(leon) Value(PROCESSOR_LEON) EnumValue +Enum(sparc_processor_type) String(leon3) Value(PROCESSOR_LEON3) + +EnumValue Enum(sparc_processor_type) String(sparclite) Value(PROCESSOR_SPARCLITE) EnumValue @@ -201,9 +204,19 @@ Enable workaround for single erratum of AT697F processor (corresponding to erratum #13 of AT697E processor) +mfix-ut699 +Target Report RejectNegative Var(sparc_fix_ut699) +Enable workarounds for the errata of the UT699 processor + Mask(LONG_DOUBLE_128) ;; Use 128-bit long double +Mask(LEON) +;; Generate code for LEON + +Mask(LEON3) +;; Generate code for LEON3 + Mask(SPARCLITE) ;; Generate code for SPARClite diff -Naur gcc-4.8.2.orig/gcc/config/sparc/sync.md gcc-4.8.2/gcc/config/sparc/sync.md --- gcc-4.8.2.orig/gcc/config/sparc/sync.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/sync.md 2014-03-30 20:21:40.627594474 +0000 @@ -161,7 +161,8 @@ (match_operand:SI 5 "const_int_operand" "") ;; is_weak (match_operand:SI 6 "const_int_operand" "") ;; mod_s (match_operand:SI 7 "const_int_operand" "")] ;; mod_f - "TARGET_V9 && (mode != DImode || TARGET_ARCH64 || TARGET_V8PLUS)" + "(TARGET_V9 || TARGET_LEON3) + && (mode != DImode || TARGET_ARCH64 || TARGET_V8PLUS)" { sparc_expand_compare_and_swap (operands); DONE; @@ -176,7 +177,7 @@ [(match_operand:I48MODE 2 "register_operand" "") (match_operand:I48MODE 3 "register_operand" "")] UNSPECV_CAS))])] - "TARGET_V9" + "TARGET_V9 || TARGET_LEON3" "") (define_insn "*atomic_compare_and_swap_1" @@ -187,7 +188,7 @@ [(match_operand:I48MODE 2 "register_operand" "r") (match_operand:I48MODE 3 "register_operand" "0")] UNSPECV_CAS))] - "TARGET_V9 && (mode == SImode || TARGET_ARCH64)" + "(TARGET_V9 || TARGET_LEON3) && (mode != DImode || TARGET_ARCH64)" "cas\t%1, %2, %0" [(set_attr "type" "multi")]) @@ -220,7 +221,7 @@ (match_operand:SI 1 "memory_operand" "") (match_operand:SI 2 "register_operand" "") (match_operand:SI 3 "const_int_operand" "")] - "TARGET_V8 || TARGET_V9" + "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699" { enum memmodel model = (enum memmodel) INTVAL (operands[3]); @@ -236,7 +237,7 @@ UNSPECV_SWAP)) (set (match_dup 1) (match_operand:SI 2 "register_operand" "0"))] - "TARGET_V8 || TARGET_V9" + "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699" "swap\t%1, %0" [(set_attr "type" "multi")]) @@ -244,7 +245,7 @@ [(match_operand:QI 0 "register_operand" "") (match_operand:QI 1 "memory_operand" "") (match_operand:SI 2 "const_int_operand" "")] - "" + "!sparc_fix_ut699" { enum memmodel model = (enum memmodel) INTVAL (operands[2]); rtx ret; @@ -268,6 +269,6 @@ (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")] UNSPECV_LDSTUB)) (set (match_dup 1) (const_int -1))] - "" + "!sparc_fix_ut699" "ldstub\t%1, %0" [(set_attr "type" "multi")]) diff -Naur gcc-4.8.2.orig/gcc/config/sparc/t-rtems gcc-4.8.2/gcc/config/sparc/t-rtems --- gcc-4.8.2.orig/gcc/config/sparc/t-rtems 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/t-rtems 2014-03-30 20:21:40.627594474 +0000 @@ -17,6 +17,6 @@ # . # -MULTILIB_OPTIONS = msoft-float mcpu=v8 -MULTILIB_DIRNAMES = soft v8 +MULTILIB_OPTIONS = msoft-float mcpu=v8/mcpu=leon3 +MULTILIB_DIRNAMES = soft v8 leon3 MULTILIB_MATCHES = msoft-float=mno-fpu diff -Naur gcc-4.8.2.orig/gcc/config/sparc/t-sparc gcc-4.8.2/gcc/config/sparc/t-sparc --- gcc-4.8.2.orig/gcc/config/sparc/t-sparc 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/sparc/t-sparc 2014-03-30 20:21:40.627594474 +0000 @@ -23,7 +23,7 @@ insn-codes.h conditions.h output.h $(INSN_ATTR_H) $(FLAGS_H) \ $(FUNCTION_H) $(EXCEPT_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H) \ $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) debug.h $(TARGET_H) \ - $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) \ + $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) $(TREE_PASS_H) \ langhooks.h reload.h $(PARAMS_H) $(DF_H) $(OPTS_H) \ gt-sparc.h diff -Naur gcc-4.8.2.orig/gcc/config/tilegx/sync.md gcc-4.8.2/gcc/config/tilegx/sync.md --- gcc-4.8.2.orig/gcc/config/tilegx/sync.md 2013-03-21 22:27:07.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilegx/sync.md 2014-03-30 20:21:40.627594474 +0000 @@ -150,15 +150,22 @@ (match_operand:SI 3 "const_int_operand" "")] ;; model "" { + rtx addend; enum memmodel model = (enum memmodel) INTVAL (operands[3]); if (operands[2] != const0_rtx) - emit_move_insn (operands[2], gen_rtx_NEG (mode, operands[2])); + { + addend = gen_reg_rtx (mode); + emit_move_insn (addend, + gen_rtx_MINUS (mode, const0_rtx, operands[2])); + } + else + addend = operands[2]; tilegx_pre_atomic_barrier (model); emit_insn (gen_atomic_fetch_add_bare (operands[0], operands[1], - operands[2])); + addend)); tilegx_post_atomic_barrier (model); DONE; }) diff -Naur gcc-4.8.2.orig/gcc/config/tilegx/tilegx-c.c gcc-4.8.2/gcc/config/tilegx/tilegx-c.c --- gcc-4.8.2.orig/gcc/config/tilegx/tilegx-c.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilegx/tilegx-c.c 2014-03-30 20:21:40.627594474 +0000 @@ -47,6 +47,9 @@ if (TARGET_32BIT) builtin_define ("__tilegx32__"); + builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); + builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); + TILEGX_CPU_CPP_ENDIAN_BUILTINS (); GNU_USER_TARGET_OS_CPP_BUILTINS (); } diff -Naur gcc-4.8.2.orig/gcc/config/tilegx/tilegx.c gcc-4.8.2/gcc/config/tilegx/tilegx.c --- gcc-4.8.2.orig/gcc/config/tilegx/tilegx.c 2013-03-27 06:29:49.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilegx/tilegx.c 2014-03-30 20:21:40.627594474 +0000 @@ -702,6 +702,16 @@ } +/* Implement TARGET_EXPAND_TO_RTL_HOOK. */ +static void +tilegx_expand_to_rtl_hook (void) +{ + /* Exclude earlier sets of crtl->uses_pic_offset_table, because we + only care about uses actually emitted. */ + crtl->uses_pic_offset_table = 0; +} + + /* Implement TARGET_SHIFT_TRUNCATION_MASK. DImode shifts use the mode matching insns and therefore guarantee that the shift count is modulo 64. SImode shifts sometimes use the 64 bit version so do @@ -3543,6 +3553,12 @@ } if (!pat) return NULL_RTX; + + /* If we are generating a prefetch, tell the scheduler not to move + it around. */ + if (GET_CODE (pat) == PREFETCH) + PREFETCH_SCHEDULE_BARRIER_P (pat) = true; + emit_insn (pat); if (nonvoid) @@ -4368,10 +4384,12 @@ basic_block bb; FOR_EACH_BB (bb) { - rtx insn, next; + rtx insn, next, prev; rtx end = NEXT_INSN (BB_END (bb)); - for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn; insn = next) + prev = NULL_RTX; + for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn; + prev = insn, insn = next) { next = next_insn_to_bundle (NEXT_INSN (insn), end); @@ -4396,6 +4414,18 @@ PUT_MODE (insn, SImode); } } + + /* Delete barrier insns, because they can mess up the + emitting of bundle braces. If it is end-of-bundle, then + the previous insn must be marked end-of-bundle. */ + if (get_attr_type (insn) == TYPE_NOTHING) { + if (GET_MODE (insn) == QImode && prev != NULL + && GET_MODE (prev) == SImode) + { + PUT_MODE (prev, QImode); + } + delete_insn (insn); + } } } } @@ -5498,6 +5528,9 @@ #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS tilegx_rtx_costs +#undef TARGET_EXPAND_TO_RTL_HOOK +#define TARGET_EXPAND_TO_RTL_HOOK tilegx_expand_to_rtl_hook + #undef TARGET_SHIFT_TRUNCATION_MASK #define TARGET_SHIFT_TRUNCATION_MASK tilegx_shift_truncation_mask diff -Naur gcc-4.8.2.orig/gcc/config/tilegx/tilegx.md gcc-4.8.2/gcc/config/tilegx/tilegx.md --- gcc-4.8.2.orig/gcc/config/tilegx/tilegx.md 2013-03-27 06:27:57.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilegx/tilegx.md 2014-03-30 20:21:40.630928019 +0000 @@ -5076,10 +5076,8 @@ ;; Network intrinsics -;; Note the "pseudo" text is handled specially by the -;; asm_output_opcode routine. If the output is an empty string, the -;; instruction would bypass the asm_output_opcode routine, bypassing -;; the bundle handling code. +;; Note the this barrier is of type "nothing," which is deleted after +;; the final scheduling pass so that nothing is emitted for it. (define_insn "tilegx_network_barrier" [(unspec_volatile:SI [(const_int 0)] UNSPEC_NETWORK_BARRIER)] "" diff -Naur gcc-4.8.2.orig/gcc/config/tilepro/tilepro-c.c gcc-4.8.2/gcc/config/tilepro/tilepro-c.c --- gcc-4.8.2.orig/gcc/config/tilepro/tilepro-c.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilepro/tilepro-c.c 2014-03-30 20:21:40.630928019 +0000 @@ -44,6 +44,11 @@ builtin_define ("__tile_chip__=1"); builtin_define ("__tile_chip_rev__=0"); + builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); + builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); + builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); + builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); + TILEPRO_CPU_CPP_ENDIAN_BUILTINS (); GNU_USER_TARGET_OS_CPP_BUILTINS (); } diff -Naur gcc-4.8.2.orig/gcc/config/tilepro/tilepro.c gcc-4.8.2/gcc/config/tilepro/tilepro.c --- gcc-4.8.2.orig/gcc/config/tilepro/tilepro.c 2013-03-26 06:13:34.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilepro/tilepro.c 2014-03-30 20:21:40.630928019 +0000 @@ -3167,6 +3167,12 @@ } if (!pat) return NULL_RTX; + + /* If we are generating a prefetch, tell the scheduler not to move + it around. */ + if (GET_CODE (pat) == PREFETCH) + PREFETCH_SCHEDULE_BARRIER_P (pat) = true; + emit_insn (pat); if (nonvoid) diff -Naur gcc-4.8.2.orig/gcc/config/tilepro/tilepro.md gcc-4.8.2/gcc/config/tilepro/tilepro.md --- gcc-4.8.2.orig/gcc/config/tilepro/tilepro.md 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/config/tilepro/tilepro.md 2014-03-30 20:21:40.630928019 +0000 @@ -795,7 +795,7 @@ (define_expand "ctzdi2" [(set (match_operand:DI 0 "register_operand" "") - (ctz:DI (match_operand:DI 1 "reg_or_0_operand" "")))] + (ctz:DI (match_operand:DI 1 "register_operand" "")))] "" { rtx lo, hi, ctz_lo, ctz_hi, ctz_hi_plus_32, result; @@ -823,7 +823,7 @@ (define_expand "clzdi2" [(set (match_operand:DI 0 "register_operand" "") - (clz:DI (match_operand:DI 1 "reg_or_0_operand" "")))] + (clz:DI (match_operand:DI 1 "register_operand" "")))] "" { rtx lo, hi, clz_lo, clz_hi, clz_lo_plus_32, result; @@ -851,7 +851,7 @@ (define_expand "ffsdi2" [(set (match_operand:DI 0 "register_operand" "") - (ffs:DI (match_operand:DI 1 "reg_or_0_operand" "")))] + (ffs:DI (match_operand:DI 1 "register_operand" "")))] "" { rtx lo, hi, ctz_lo, ctz_hi, ctz_hi_plus_32, ctz, ctz_plus_1,ctz_cond; diff -Naur gcc-4.8.2.orig/gcc/config.gcc gcc-4.8.2/gcc/config.gcc --- gcc-4.8.2.orig/gcc/config.gcc 2013-10-03 00:47:24.000000000 +0000 +++ gcc-4.8.2/gcc/config.gcc 2014-03-30 20:21:40.630928019 +0000 @@ -1761,6 +1761,14 @@ tmake_file="${tmake_file} microblaze/t-microblaze-linux" ;; microblaze*-*-rtems*) + case $target in + microblazeel-*) + tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=0" + ;; + microblaze-*) + tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321" + ;; + esac tm_file="${tm_file} dbxelf.h" tm_file="${tm_file} microblaze/rtems.h rtems.h newlib-stdint.h" c_target_objs="${c_target_objs} microblaze-c.o" @@ -2963,11 +2971,18 @@ with_cpu=8540 fi ;; - sparc-leon*-*) - with_cpu=v8; - ;; sparc*-*-*) - with_cpu="`echo ${target} | sed 's/-.*$//'`" + case ${target} in + *-leon-*) + with_cpu=leon + ;; + *-leon[3-9]*) + with_cpu=leon3 + ;; + *) + with_cpu="`echo ${target} | sed 's/-.*$//'`" + ;; + esac ;; esac @@ -3587,7 +3602,7 @@ case ${val} in "" | sparc | sparcv9 | sparc64 \ | v7 | cypress \ - | v8 | supersparc | hypersparc | leon \ + | v8 | supersparc | hypersparc | leon | leon3 \ | sparclite | f930 | f934 | sparclite86x \ | sparclet | tsc701 \ | v9 | ultrasparc | ultrasparc3 | niagara | niagara2 \ @@ -3745,15 +3760,6 @@ cxx_target_objs="${cxx_target_objs} sh-c.o" ;; - sparc-leon*-*) - if test x$with_tune = x ; then - with_tune=leon; - fi - - # The SPARC port checks this value at compile-time. - target_cpu_default2="TARGET_CPU_$with_cpu" - ;; - sparc*-*-*) # Some standard aliases. case x$with_cpu in @@ -3765,6 +3771,17 @@ ;; esac + if test x$with_tune = x ; then + case ${target} in + *-leon-*) + with_tune=leon + ;; + *-leon[3-9]*) + with_tune=leon3 + ;; + esac + fi + # The SPARC port checks this value at compile-time. target_cpu_default2="TARGET_CPU_$with_cpu" ;; diff -Naur gcc-4.8.2.orig/gcc/config.in gcc-4.8.2/gcc/config.in --- gcc-4.8.2.orig/gcc/config.in 2013-10-16 07:27:58.000000000 +0000 +++ gcc-4.8.2/gcc/config.in 2014-03-30 20:21:40.630928019 +0000 @@ -363,6 +363,12 @@ #endif +/* Define if your assembler supports the 'ud2' mnemonic. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_IX86_UD2 +#endif + + /* Define if your assembler supports the lituse_jsrdirect relocation. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_JSRDIRECT_RELOCS @@ -375,6 +381,12 @@ #endif +/* Define if your assembler supports LEON instructions. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_LEON +#endif + + /* Define if the assembler won't complain about a line such as # 0 "" 2. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_LINE_ZERO diff -Naur gcc-4.8.2.orig/gcc/configure gcc-4.8.2/gcc/configure --- gcc-4.8.2.orig/gcc/configure 2013-06-19 01:18:38.000000000 +0000 +++ gcc-4.8.2/gcc/configure 2014-03-30 20:21:40.634261520 +0000 @@ -11202,13 +11202,11 @@ /* | A-Za-z:\\/* ) realsrcdir=${srcdir};; *) realsrcdir=../${srcdir};; esac - saved_CFLAGS="${CFLAGS}" CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \ - LDFLAGS="${LDFLAGS_FOR_BUILD}" \ + LDFLAGS="${LDFLAGS_FOR_BUILD}" GMPINC="" \ ${realsrcdir}/configure \ --enable-languages=${enable_languages-all} \ --target=$target_alias --host=$build_alias --build=$build_alias - CFLAGS="${saved_CFLAGS}" # We just finished tests for the build machine, so rename # the file auto-build.h in the gcc directory. @@ -11703,6 +11701,7 @@ if test x$build != x$host || test "x$coverage_flags" != x then BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' + BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CXXFLAGS_FOR_BUILD)' BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' fi @@ -17828,7 +17827,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17831 "configure" +#line 17830 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17934,7 +17933,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17937 "configure" +#line 17936 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -24263,6 +24262,43 @@ $as_echo "#define HAVE_AS_SPARC4 1" >>confdefs.h fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for LEON instructions" >&5 +$as_echo_n "checking assembler for LEON instructions... " >&6; } +if test "${gcc_cv_as_sparc_leon+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_sparc_leon=no + if test x$gcc_cv_as != x; then + $as_echo '.text + .register %g2, #scratch + .register %g3, #scratch + .align 4 + smac %g2, %g3, %g1 + umac %g2, %g3, %g1 + cas [%g2], %g3, %g1' > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -Aleon -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_sparc_leon=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_sparc_leon" >&5 +$as_echo "$gcc_cv_as_sparc_leon" >&6; } +if test $gcc_cv_as_sparc_leon = yes; then + +$as_echo "#define HAVE_AS_LEON 1" >>confdefs.h + +fi ;; i[34567]86-*-* | x86_64-*-*) @@ -24745,6 +24781,10 @@ # These two are used unconditionally by i386.[ch]; it is to be defined # to 1 if the feature is present, 0 otherwise. + as_ix86_gotoff_in_data_opt= + if test x$gas = xyes; then + as_ix86_gotoff_in_data_opt="--32" + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for GOTOFF in data" >&5 $as_echo_n "checking assembler for GOTOFF in data... " >&6; } if test "${gcc_cv_as_ix86_gotoff_in_data+set}" = set; then : @@ -24761,7 +24801,7 @@ nop .data .long .L0@GOTOFF' > conftest.s - if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' + if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gotoff_in_data_opt -o conftest.o conftest.s >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -24822,6 +24862,37 @@ fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for ud2 mnemonic" >&5 +$as_echo_n "checking assembler for ud2 mnemonic... " >&6; } +if test "${gcc_cv_as_ix86_ud2+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_ix86_ud2=no + if test x$gcc_cv_as != x; then + $as_echo 'ud2' > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_ix86_ud2=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_ix86_ud2" >&5 +$as_echo "$gcc_cv_as_ix86_ud2" >&6; } +if test $gcc_cv_as_ix86_ud2 = yes; then + +$as_echo "#define HAVE_AS_IX86_UD2 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for R_386_TLS_GD_PLT reloc" >&5 $as_echo_n "checking assembler for R_386_TLS_GD_PLT reloc... " >&6; } if test "${gcc_cv_as_ix86_tlsgdplt+set}" = set; then : @@ -27239,8 +27310,8 @@ $as_echo_n "checking for exported symbols... " >&6; } if test "x$export_sym_check" != x; then echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c - ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest > /dev/null 2>&1 - if $export_sym_check conftest | grep foobar > /dev/null; then + ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1 + if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then : # No need to use a flag { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -27249,8 +27320,8 @@ $as_echo "yes" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -rdynamic" >&5 $as_echo_n "checking for -rdynamic... " >&6; } - ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest > /dev/null 2>&1 - if $export_sym_check conftest | grep foobar > /dev/null; then + ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1 + if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then plugin_rdynamic=yes pluginlibs="-rdynamic" else diff -Naur gcc-4.8.2.orig/gcc/configure.ac gcc-4.8.2/gcc/configure.ac --- gcc-4.8.2.orig/gcc/configure.ac 2013-06-19 01:18:38.000000000 +0000 +++ gcc-4.8.2/gcc/configure.ac 2014-03-30 20:21:40.634261520 +0000 @@ -1516,13 +1516,11 @@ /* | [A-Za-z]:[\\/]* ) realsrcdir=${srcdir};; *) realsrcdir=../${srcdir};; esac - saved_CFLAGS="${CFLAGS}" CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \ - LDFLAGS="${LDFLAGS_FOR_BUILD}" \ + LDFLAGS="${LDFLAGS_FOR_BUILD}" GMPINC="" \ ${realsrcdir}/configure \ --enable-languages=${enable_languages-all} \ --target=$target_alias --host=$build_alias --build=$build_alias - CFLAGS="${saved_CFLAGS}" # We just finished tests for the build machine, so rename # the file auto-build.h in the gcc directory. @@ -1887,6 +1885,7 @@ if test x$build != x$host || test "x$coverage_flags" != x then BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' + BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CXXFLAGS_FOR_BUILD)' BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' fi @@ -3611,6 +3610,19 @@ kasumi_fi_xor %f46, %f48, %f50, %f52],, [AC_DEFINE(HAVE_AS_SPARC4, 1, [Define if your assembler supports SPARC4 instructions.])]) + + gcc_GAS_CHECK_FEATURE([LEON instructions], + gcc_cv_as_sparc_leon,, + [-Aleon], + [.text + .register %g2, #scratch + .register %g3, #scratch + .align 4 + smac %g2, %g3, %g1 + umac %g2, %g3, %g1 + cas [[%g2]], %g3, %g1],, + [AC_DEFINE(HAVE_AS_LEON, 1, + [Define if your assembler supports LEON instructions.])]) ;; changequote(,)dnl @@ -3749,8 +3761,13 @@ # These two are used unconditionally by i386.[ch]; it is to be defined # to 1 if the feature is present, 0 otherwise. + as_ix86_gotoff_in_data_opt= + if test x$gas = xyes; then + as_ix86_gotoff_in_data_opt="--32" + fi gcc_GAS_CHECK_FEATURE([GOTOFF in data], - gcc_cv_as_ix86_gotoff_in_data, [2,11,0],, + gcc_cv_as_ix86_gotoff_in_data, [2,11,0], + [$as_ix86_gotoff_in_data_opt], [ .text .L0: nop @@ -3772,6 +3789,12 @@ [AC_DEFINE(HAVE_AS_IX86_REP_LOCK_PREFIX, 1, [Define if the assembler supports 'rep , lock '.])]) + gcc_GAS_CHECK_FEATURE([ud2 mnemonic], + gcc_cv_as_ix86_ud2,,, + [ud2],, + [AC_DEFINE(HAVE_AS_IX86_UD2, 1, + [Define if your assembler supports the 'ud2' mnemonic.])]) + gcc_GAS_CHECK_FEATURE([R_386_TLS_GD_PLT reloc], gcc_cv_as_ix86_tlsgdplt,,, [call tls_gd@tlsgdplt], @@ -5193,15 +5216,15 @@ AC_MSG_CHECKING([for exported symbols]) if test "x$export_sym_check" != x; then echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c - ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest > /dev/null 2>&1 - if $export_sym_check conftest | grep foobar > /dev/null; then + ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1 + if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then : # No need to use a flag AC_MSG_RESULT([yes]) else AC_MSG_RESULT([yes]) AC_MSG_CHECKING([for -rdynamic]) - ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest > /dev/null 2>&1 - if $export_sym_check conftest | grep foobar > /dev/null; then + ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1 + if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then plugin_rdynamic=yes pluginlibs="-rdynamic" else diff -Naur gcc-4.8.2.orig/gcc/cp/call.c gcc-4.8.2/gcc/cp/call.c --- gcc-4.8.2.orig/gcc/cp/call.c 2013-07-25 15:07:27.000000000 +0000 +++ gcc-4.8.2/gcc/cp/call.c 2014-03-30 20:21:40.637594959 +0000 @@ -892,6 +892,9 @@ if (i < CONSTRUCTOR_NELTS (ctor)) val = CONSTRUCTOR_ELT (ctor, i)->value; + else if (TREE_CODE (ftype) == REFERENCE_TYPE) + /* Value-initialization of reference is ill-formed. */ + return NULL; else { if (empty_ctor == NULL_TREE) @@ -5806,9 +5809,11 @@ && convs->kind != ck_ambig && (convs->kind != ck_ref_bind || convs->user_conv_p) - && convs->kind != ck_rvalue + && (convs->kind != ck_rvalue + || SCALAR_TYPE_P (totype)) && convs->kind != ck_base) { + bool complained = false; conversion *t = convs; /* Give a helpful error if this is bad because of excess braces. */ @@ -5816,7 +5821,14 @@ && SCALAR_TYPE_P (totype) && CONSTRUCTOR_NELTS (expr) > 0 && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value)) - permerror (loc, "too many braces around initializer for %qT", totype); + { + complained = true; + permerror (loc, "too many braces around initializer " + "for %qT", totype); + while (BRACE_ENCLOSED_INITIALIZER_P (expr) + && CONSTRUCTOR_NELTS (expr) == 1) + expr = CONSTRUCTOR_ELT (expr, 0)->value; + } for (; t ; t = next_conversion (t)) { @@ -5853,8 +5865,9 @@ break; } - permerror (loc, "invalid conversion from %qT to %qT", - TREE_TYPE (expr), totype); + if (!complained) + permerror (loc, "invalid conversion from %qT to %qT", + TREE_TYPE (expr), totype); if (fn) permerror (DECL_SOURCE_LOCATION (fn), " initializing argument %P of %qD", argnum, fn); @@ -5999,6 +6012,8 @@ to avoid the error about taking the address of a temporary. */ array = cp_build_addr_expr (array, complain); array = cp_convert (build_pointer_type (elttype), array, complain); + if (array == error_mark_node) + return error_mark_node; /* Build up the initializer_list object. */ totype = complete_type (totype); @@ -6023,8 +6038,11 @@ return fold_if_not_in_template (expr); } expr = reshape_init (totype, expr, complain); - return get_target_expr_sfinae (digest_init (totype, expr, complain), + expr = get_target_expr_sfinae (digest_init (totype, expr, complain), complain); + if (expr != error_mark_node) + TARGET_EXPR_LIST_INIT_P (expr) = true; + return expr; default: break; @@ -7414,7 +7432,7 @@ struct z_candidate *candidates = 0, *cand; tree explicit_targs = NULL_TREE; tree basetype = NULL_TREE; - tree access_binfo; + tree access_binfo, binfo; tree optype; tree first_mem_arg = NULL_TREE; tree instance_ptr; @@ -7454,6 +7472,7 @@ if (!conversion_path) conversion_path = BASELINK_BINFO (fns); access_binfo = BASELINK_ACCESS_BINFO (fns); + binfo = BASELINK_BINFO (fns); optype = BASELINK_OPTYPE (fns); fns = BASELINK_FUNCTIONS (fns); if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) @@ -7697,13 +7716,13 @@ { /* Optimize away vtable lookup if we know that this function can't be overridden. We need to check if - the context and the instance type are the same, + the context and the type where we found fn are the same, actually FN might be defined in a different class type because of a using-declaration. In this case, we do not want to perform a non-virtual call. */ if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL) && same_type_ignoring_top_level_qualifiers_p - (DECL_CONTEXT (fn), TREE_TYPE (instance)) + (DECL_CONTEXT (fn), BINFO_TYPE (binfo)) && resolves_to_fixed_type_p (instance, 0)) flags |= LOOKUP_NONVIRTUAL; if (explicit_targs) diff -Naur gcc-4.8.2.orig/gcc/cp/cp-tree.h gcc-4.8.2/gcc/cp/cp-tree.h --- gcc-4.8.2.orig/gcc/cp/cp-tree.h 2013-08-20 12:59:37.000000000 +0000 +++ gcc-4.8.2/gcc/cp/cp-tree.h 2014-03-30 20:21:40.637594959 +0000 @@ -344,7 +344,8 @@ /* Returns true iff NODE is a BASELINK. */ #define BASELINK_P(NODE) \ (TREE_CODE (NODE) == BASELINK) -/* The BINFO indicating the base from which the BASELINK_FUNCTIONS came. */ +/* The BINFO indicating the base in which lookup found the + BASELINK_FUNCTIONS. */ #define BASELINK_BINFO(NODE) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->binfo) /* The functions referred to by the BASELINK; either a FUNCTION_DECL, diff -Naur gcc-4.8.2.orig/gcc/cp/cvt.c gcc-4.8.2/gcc/cp/cvt.c --- gcc-4.8.2.orig/gcc/cp/cvt.c 2013-08-20 12:59:37.000000000 +0000 +++ gcc-4.8.2/gcc/cp/cvt.c 2014-03-30 20:21:40.637594959 +0000 @@ -203,13 +203,13 @@ if (null_ptr_cst_p (expr)) { - if (complain & tf_warning) - maybe_warn_zero_as_null_pointer_constant (expr, loc); - if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, /*c_cast_p=*/false, complain); + if (complain & tf_warning) + maybe_warn_zero_as_null_pointer_constant (expr, loc); + /* A NULL pointer-to-data-member is represented by -1, not by zero. */ tree val = (TYPE_PTRDATAMEM_P (type) @@ -743,6 +743,7 @@ unspecified. */ if ((complain & tf_warning) && TREE_CODE (e) == INTEGER_CST + && ENUM_UNDERLYING_TYPE (type) && !int_fits_type_p (e, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " diff -Naur gcc-4.8.2.orig/gcc/cp/decl.c gcc-4.8.2/gcc/cp/decl.c --- gcc-4.8.2.orig/gcc/cp/decl.c 2013-10-08 22:29:49.000000000 +0000 +++ gcc-4.8.2/gcc/cp/decl.c 2014-03-30 20:21:40.637594959 +0000 @@ -1867,9 +1867,9 @@ /* Merge the data types specified in the two decls. */ newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); - /* If merge_types produces a non-typedef type, just use the old type. */ - if (TREE_CODE (newdecl) == TYPE_DECL - && newtype == DECL_ORIGINAL_TYPE (newdecl)) + /* For typedefs use the old type, as the new type's DECL_NAME points + at newdecl, which will be ggc_freed. */ + if (TREE_CODE (newdecl) == TYPE_DECL) newtype = oldtype; if (TREE_CODE (newdecl) == VAR_DECL) @@ -8193,7 +8193,9 @@ abi_1_itype = error_mark_node; } - size = maybe_constant_value (size); + if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) + size = maybe_constant_value (size); + if (!TREE_CONSTANT (size)) size = osize; } @@ -11891,7 +11893,10 @@ if (decl && (DECL_CLASS_TEMPLATE_P (decl) - || DECL_TEMPLATE_TEMPLATE_PARM_P (decl))) + /* If scope is ts_current we're defining a class, so ignore a + template template parameter. */ + || (scope != ts_current + && DECL_TEMPLATE_TEMPLATE_PARM_P (decl)))) decl = DECL_TEMPLATE_RESULT (decl); if (decl && TREE_CODE (decl) == TYPE_DECL) diff -Naur gcc-4.8.2.orig/gcc/cp/decl2.c gcc-4.8.2/gcc/cp/decl2.c --- gcc-4.8.2.orig/gcc/cp/decl2.c 2013-05-20 13:37:44.000000000 +0000 +++ gcc-4.8.2/gcc/cp/decl2.c 2014-03-30 20:21:40.637594959 +0000 @@ -2884,7 +2884,7 @@ TREE_PUBLIC (fn) = TREE_PUBLIC (var); DECL_ARTIFICIAL (fn) = true; DECL_COMDAT (fn) = DECL_COMDAT (var); - DECL_EXTERNAL (fn) = true; + DECL_EXTERNAL (fn) = DECL_EXTERNAL (var); if (DECL_ONE_ONLY (var)) make_decl_one_only (fn, cxx_comdat_group (fn)); if (TREE_PUBLIC (var)) @@ -3946,6 +3946,8 @@ if (TREE_PUBLIC (var)) { tree single_init_fn = get_tls_init_fn (var); + if (single_init_fn == NULL_TREE) + continue; cgraph_node *alias = cgraph_same_body_alias (cgraph_get_create_node (fn), single_init_fn, fn); @@ -3960,6 +3962,22 @@ expand_or_defer_fn (finish_function (0)); } +/* The entire file is now complete. If requested, dump everything + to a file. */ + +static void +dump_tu (void) +{ + int flags; + FILE *stream = dump_begin (TDI_tu, &flags); + + if (stream) + { + dump_node (global_namespace, flags & ~TDF_SLIM, stream); + dump_end (TDI_tu, stream); + } +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -3990,6 +4008,7 @@ if (pch_file) { c_common_write_pch (); + dump_tu (); return; } @@ -4359,16 +4378,7 @@ /* The entire file is now complete. If requested, dump everything to a file. */ - { - int flags; - FILE *stream = dump_begin (TDI_tu, &flags); - - if (stream) - { - dump_node (global_namespace, flags & ~TDF_SLIM, stream); - dump_end (TDI_tu, stream); - } - } + dump_tu (); if (flag_detailed_statistics) { diff -Naur gcc-4.8.2.orig/gcc/cp/except.c gcc-4.8.2/gcc/cp/except.c --- gcc-4.8.2.orig/gcc/cp/except.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/cp/except.c 2014-03-30 20:21:40.640928378 +0000 @@ -380,6 +380,9 @@ { tree type = body ? TREE_TYPE (body) : void_type_node; + if (!flag_exceptions) + return body; + if (cond && !value_dependent_expression_p (cond)) { cond = cxx_constant_value (cond); diff -Naur gcc-4.8.2.orig/gcc/cp/mangle.c gcc-4.8.2/gcc/cp/mangle.c --- gcc-4.8.2.orig/gcc/cp/mangle.c 2013-04-03 03:11:12.000000000 +0000 +++ gcc-4.8.2/gcc/cp/mangle.c 2014-03-30 20:21:40.640928378 +0000 @@ -3478,6 +3478,7 @@ if (G.need_abi_warning /* Don't do this for a fake symbol we aren't going to emit anyway. */ + && TREE_CODE (decl) != TYPE_DECL && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) { @@ -3773,7 +3774,8 @@ static void write_guarded_var_name (const tree variable) { - if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) + if (DECL_NAME (variable) + && strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) /* The name of a guard variable for a reference temporary should refer to the reference, not the temporary. */ write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); diff -Naur gcc-4.8.2.orig/gcc/cp/name-lookup.c gcc-4.8.2/gcc/cp/name-lookup.c --- gcc-4.8.2.orig/gcc/cp/name-lookup.c 2013-08-18 01:07:02.000000000 +0000 +++ gcc-4.8.2/gcc/cp/name-lookup.c 2014-03-30 20:21:40.640928378 +0000 @@ -394,7 +394,8 @@ } } -/* Strip non dependent using declarations. */ +/* Strip non dependent using declarations. If DECL is dependent, + surreptitiously create a typename_type and return it. */ tree strip_using_decl (tree decl) @@ -404,6 +405,23 @@ while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl)) decl = USING_DECL_DECLS (decl); + + if (TREE_CODE (decl) == USING_DECL && DECL_DEPENDENT_P (decl) + && USING_DECL_TYPENAME_P (decl)) + { + /* We have found a type introduced by a using + declaration at class scope that refers to a dependent + type. + + using typename :: [opt] nested-name-specifier unqualified-id ; + */ + decl = make_typename_type (TREE_TYPE (decl), + DECL_NAME (decl), + typename_type, tf_error); + if (decl != error_mark_node) + decl = TYPE_NAME (decl); + } + return decl; } @@ -5605,9 +5623,9 @@ push_using_directive (tree used) { tree ret; - timevar_start (TV_NAME_LOOKUP); + bool subtime = timevar_cond_start (TV_NAME_LOOKUP); ret = push_using_directive_1 (used); - timevar_stop (TV_NAME_LOOKUP); + timevar_cond_stop (TV_NAME_LOOKUP, subtime); return ret; } diff -Naur gcc-4.8.2.orig/gcc/cp/parser.c gcc-4.8.2/gcc/cp/parser.c --- gcc-4.8.2.orig/gcc/cp/parser.c 2013-10-02 18:27:30.000000000 +0000 +++ gcc-4.8.2/gcc/cp/parser.c 2014-03-30 20:21:40.644261804 +0000 @@ -6421,10 +6421,6 @@ /* Look for the `~'. */ cp_parser_require (parser, CPP_COMPL, RT_COMPL); - /* Once we see the ~, this has to be a pseudo-destructor. */ - if (!processing_template_decl && !cp_parser_error_occurred (parser)) - cp_parser_commit_to_tentative_parse (parser); - /* Look for the type-name again. We are not responsible for checking that it matches the first type-name. */ *type = cp_parser_nonclass_name (parser); @@ -14168,25 +14164,7 @@ /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); - if (TREE_CODE (type_decl) == USING_DECL) - { - if (!DECL_DEPENDENT_P (type_decl)) - type_decl = strip_using_decl (type_decl); - else if (USING_DECL_TYPENAME_P (type_decl)) - { - /* We have found a type introduced by a using - declaration at class scope that refers to a dependent - type. - - using typename :: [opt] nested-name-specifier unqualified-id ; - */ - type_decl = make_typename_type (TREE_TYPE (type_decl), - DECL_NAME (type_decl), - typename_type, tf_error); - if (type_decl != error_mark_node) - type_decl = TYPE_NAME (type_decl); - } - } + type_decl = strip_using_decl (type_decl); if (TREE_CODE (type_decl) != TYPE_DECL && (objc_is_id (identifier) || objc_is_class_name (identifier))) @@ -14742,7 +14720,8 @@ { underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME, /*initialized=*/0, NULL); - if (underlying_type == error_mark_node) + if (underlying_type == error_mark_node + || check_for_bare_parameter_packs (underlying_type)) underlying_type = NULL_TREE; } } @@ -22209,6 +22188,9 @@ tree cast; bool nonconst_p; + if (!type) + type = error_mark_node; + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); @@ -22576,6 +22558,9 @@ && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg)) flags = LOOKUP_NORMAL; parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags); + if (TREE_CODE (parsed_arg) == TARGET_EXPR) + /* This represents the whole initialization. */ + TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true; } } diff -Naur gcc-4.8.2.orig/gcc/cp/pt.c gcc-4.8.2/gcc/cp/pt.c --- gcc-4.8.2.orig/gcc/cp/pt.c 2013-09-13 22:22:31.000000000 +0000 +++ gcc-4.8.2/gcc/cp/pt.c 2014-03-30 20:21:40.644261804 +0000 @@ -170,7 +170,7 @@ static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree); static tree tsubst_template_parms (tree, tree, tsubst_flags_t); static void regenerate_decl_from_template (tree, tree); -static tree most_specialized_class (tree, tree, tsubst_flags_t); +static tree most_specialized_class (tree, tsubst_flags_t); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); @@ -1419,6 +1419,8 @@ = DECL_DECLARED_INLINE_P (fn); DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); + DECL_DELETED_FN (clone) + = DECL_DELETED_FN (fn); } check_specialization_namespace (tmpl); @@ -3436,7 +3438,7 @@ for (i = 0; i < num_packed; ++i, ++out_arg) TREE_VEC_ELT (result_args, out_arg) = TREE_VEC_ELT(packed, i); if (non_default_args_count > 0) - non_default_args_count += num_packed; + non_default_args_count += num_packed - 1; } else { @@ -3491,6 +3493,11 @@ || TEMPLATE_PARMS_FOR_INLINE (current_template_parms)) return true; + /* Don't complain about the injected class name, as we've already + complained about the class itself. */ + if (DECL_SELF_REFERENCE_P (decl)) + return false; + error ("declaration of %q+#D", decl); error (" shadows template parm %q+#D", olddecl); return false; @@ -4261,7 +4268,7 @@ if (COMPLETE_TYPE_P (inst_type) && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type)) { - tree spec = most_specialized_class (inst_type, maintmpl, tf_none); + tree spec = most_specialized_class (inst_type, tf_none); if (spec && TREE_TYPE (spec) == type) permerror (input_location, "partial specialization of %qT after instantiation " @@ -6672,6 +6679,8 @@ /* Store this argument. */ if (arg == error_mark_node) lost++; + if (lost) + break; TREE_VEC_ELT (new_inner_args, parm_idx) = arg; /* We are done with all of the arguments. */ @@ -8572,7 +8581,7 @@ /* Determine what specialization of the original template to instantiate. */ - t = most_specialized_class (type, templ, tf_warning_or_error); + t = most_specialized_class (type, tf_warning_or_error); if (t == error_mark_node) { TYPE_BEING_DEFINED (type) = 1; @@ -12694,27 +12703,43 @@ tsubst_expr ((NODE), args, complain, in_decl, \ integral_constant_expression_p) tree decl, init, cond, incr; - bool init_decl; init = TREE_VEC_ELT (OMP_FOR_INIT (t), i); gcc_assert (TREE_CODE (init) == MODIFY_EXPR); decl = TREE_OPERAND (init, 0); init = TREE_OPERAND (init, 1); - /* Do this before substituting into decl to handle 'auto'. */ - init_decl = (init && TREE_CODE (init) == DECL_EXPR); - init = RECUR (init); - decl = RECUR (decl); - if (init_decl) + tree decl_expr = NULL_TREE; + if (init && TREE_CODE (init) == DECL_EXPR) { - gcc_assert (!processing_template_decl); - init = DECL_INITIAL (decl); - DECL_INITIAL (decl) = NULL_TREE; + /* We need to jump through some hoops to handle declarations in the + for-init-statement, since we might need to handle auto deduction, + but we need to keep control of initialization. */ + decl_expr = init; + init = DECL_INITIAL (DECL_EXPR_DECL (init)); + decl = tsubst_decl (decl, args, complain); } + else + decl = RECUR (decl); + init = RECUR (init); + + tree auto_node = type_uses_auto (TREE_TYPE (decl)); + if (auto_node && init) + TREE_TYPE (decl) + = do_auto_deduction (TREE_TYPE (decl), init, auto_node); gcc_assert (!type_dependent_expression_p (decl)); if (!CLASS_TYPE_P (TREE_TYPE (decl))) { + if (decl_expr) + { + /* Declare the variable, but don't let that initialize it. */ + tree init_sav = DECL_INITIAL (DECL_EXPR_DECL (decl_expr)); + DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL_TREE; + RECUR (decl_expr); + DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init_sav; + } + cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i)); incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i); if (TREE_CODE (incr) == MODIFY_EXPR) @@ -12731,7 +12756,13 @@ return; } - if (init && !init_decl) + if (decl_expr) + { + /* Declare and initialize the variable. */ + RECUR (decl_expr); + init = NULL_TREE; + } + else if (init) { tree c; for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c)) @@ -13710,6 +13741,10 @@ RETURN (r); } + case POINTER_PLUS_EXPR: + return fold_build_pointer_plus (RECUR (TREE_OPERAND (t, 0)), + RECUR (TREE_OPERAND (t, 1))); + case SCOPE_REF: RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true, /*address_p=*/false)); @@ -14471,12 +14506,12 @@ case TRAIT_EXPR: { - tree type1 = tsubst_copy (TRAIT_EXPR_TYPE1 (t), args, - complain, in_decl); + tree type1 = tsubst (TRAIT_EXPR_TYPE1 (t), args, + complain, in_decl); tree type2 = TRAIT_EXPR_TYPE2 (t); if (type2) - type2 = tsubst_copy (type2, args, complain, in_decl); + type2 = tsubst (type2, args, complain, in_decl); RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2)); } @@ -14778,6 +14813,8 @@ /* Instantiation of the function happens in the context of the function template, not the context of the overload resolution we're doing. */ push_to_top_level (); + struct pointer_map_t *saved_local_specializations = local_specializations; + local_specializations = NULL; /* If there are dependent arguments, e.g. because we're doing partial ordering, make sure processing_template_decl stays set. */ if (uses_template_parms (targ_ptr)) @@ -14793,6 +14830,7 @@ targ_ptr, complain, gen_tmpl); if (DECL_CLASS_SCOPE_P (gen_tmpl)) pop_nested_class (); + local_specializations = saved_local_specializations; pop_from_top_level (); if (fndecl == error_mark_node) @@ -15192,8 +15230,11 @@ /* If we're looking for an exact match, check that what we got is indeed an exact match. It might not be if some template - parameters are used in non-deduced contexts. */ - if (strict == DEDUCE_EXACT) + parameters are used in non-deduced contexts. But don't check + for an exact match if we have dependent template arguments; + in that case we're doing partial ordering, and we already know + that we have two candidates that will provide the actual type. */ + if (strict == DEDUCE_EXACT && !any_dependent_template_arguments_p (targs)) { tree substed = TREE_TYPE (decl); unsigned int i; @@ -15749,7 +15790,7 @@ if (subargs != error_mark_node && !any_dependent_template_arguments_p (subargs)) { - elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE); + elem = TREE_TYPE (instantiate_template (fn, subargs, tf_none)); if (try_one_overload (tparms, targs, tempargs, parm, elem, strict, sub_strict, addr_p, explain_p) && (!goodfn || !same_type_p (goodfn, elem))) @@ -16207,6 +16248,9 @@ tree pattern = PACK_EXPANSION_PATTERN (parm); tree pack, packs = NULL_TREE; int i, start = TREE_VEC_LENGTH (packed_parms) - 1; + + packed_args = expand_template_argument_pack (packed_args); + int len = TREE_VEC_LENGTH (packed_args); /* Determine the parameter packs we will be deducing from the @@ -16574,9 +16618,11 @@ if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg)) return unify_template_deduction_failure (explain_p, parm, arg); - { tree parmvec = TYPE_TI_ARGS (parm); + /* An alias template name is never deduced. */ + if (TYPE_ALIAS_P (arg)) + arg = strip_typedefs (arg); tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg)); tree full_argvec = add_to_template_args (targs, argvec); tree parm_parms @@ -17553,7 +17599,7 @@ return -1; } -/* Determine which of two partial specializations of MAIN_TMPL is more +/* Determine which of two partial specializations of TMPL is more specialized. PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding @@ -17569,7 +17615,7 @@ two templates is more specialized. */ static int -more_specialized_class (tree main_tmpl, tree pat1, tree pat2) +more_specialized_class (tree tmpl, tree pat1, tree pat2) { tree targs; tree tmpl1, tmpl2; @@ -17584,7 +17630,7 @@ types in the arguments, and we need our dependency check functions to behave correctly. */ ++processing_template_decl; - targs = get_class_bindings (main_tmpl, TREE_VALUE (pat1), + targs = get_class_bindings (tmpl, TREE_VALUE (pat1), CLASSTYPE_TI_ARGS (tmpl1), CLASSTYPE_TI_ARGS (tmpl2)); if (targs) @@ -17593,7 +17639,7 @@ any_deductions = true; } - targs = get_class_bindings (main_tmpl, TREE_VALUE (pat2), + targs = get_class_bindings (tmpl, TREE_VALUE (pat2), CLASSTYPE_TI_ARGS (tmpl2), CLASSTYPE_TI_ARGS (tmpl1)); if (targs) @@ -17673,7 +17719,7 @@ } /* Return the innermost template arguments that, when applied to a partial - specialization of MAIN_TMPL whose innermost template parameters are + specialization of TMPL whose innermost template parameters are TPARMS, and whose specialization arguments are SPEC_ARGS, yield the ARGS. @@ -17688,7 +17734,7 @@ is bound to `double'. */ static tree -get_class_bindings (tree main_tmpl, tree tparms, tree spec_args, tree args) +get_class_bindings (tree tmpl, tree tparms, tree spec_args, tree args) { int i, ntparms = TREE_VEC_LENGTH (tparms); tree deduced_args; @@ -17728,8 +17774,8 @@ `T' is `A' but unify () does not check whether `typename T::X' is `int'. */ spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE); - spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (main_tmpl), - spec_args, main_tmpl, + spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), + spec_args, tmpl, tf_none, false, false); if (spec_args == error_mark_node /* We only need to check the innermost arguments; the other @@ -17877,30 +17923,30 @@ } /* Return the most specialized of the class template partial - specializations of TMPL which can produce TYPE, a specialization of - TMPL. The value returned is actually a TREE_LIST; the TREE_TYPE is + specializations which can produce TYPE, a specialization of some class + template. The value returned is actually a TREE_LIST; the TREE_TYPE is a _TYPE node corresponding to the partial specialization, while the TREE_PURPOSE is the set of template arguments that must be substituted into the TREE_TYPE in order to generate TYPE. If the choice of partial specialization is ambiguous, a diagnostic is issued, and the error_mark_node is returned. If there are no - partial specializations of TMPL matching TYPE, then NULL_TREE is - returned. */ + partial specializations matching TYPE, then NULL_TREE is + returned, indicating that the primary template should be used. */ static tree -most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) +most_specialized_class (tree type, tsubst_flags_t complain) { tree list = NULL_TREE; tree t; tree champ; int fate; bool ambiguous_p; - tree args; tree outer_args = NULL_TREE; - tmpl = most_general_template (tmpl); - args = CLASSTYPE_TI_ARGS (type); + tree tmpl = CLASSTYPE_TI_TEMPLATE (type); + tree main_tmpl = most_general_template (tmpl); + tree args = CLASSTYPE_TI_ARGS (type); /* For determining which partial specialization to use, only the innermost args are interesting. */ @@ -17910,7 +17956,7 @@ args = INNERMOST_TEMPLATE_ARGS (args); } - for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t)) + for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t)) { tree partial_spec_args; tree spec_args; @@ -17944,8 +17990,7 @@ partial_spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - add_to_template_args (outer_args, - partial_spec_args), + partial_spec_args, tmpl, tf_none, /*require_all_args=*/true, /*use_default_args=*/true); @@ -18553,6 +18598,10 @@ { tree fntype, spec, noex, clone; + /* Don't instantiate a noexcept-specification from template context. */ + if (processing_template_decl) + return; + if (DECL_CLONED_FUNCTION_P (fn)) fn = DECL_CLONED_FUNCTION (fn); fntype = TREE_TYPE (fn); @@ -19955,6 +20004,10 @@ if (TREE_CODE (expression) == SCOPE_REF) return false; + /* Always dependent, on the number of arguments if nothing else. */ + if (TREE_CODE (expression) == EXPR_PACK_EXPANSION) + return true; + if (BASELINK_P (expression)) expression = BASELINK_FUNCTIONS (expression); diff -Naur gcc-4.8.2.orig/gcc/cp/semantics.c gcc-4.8.2/gcc/cp/semantics.c --- gcc-4.8.2.orig/gcc/cp/semantics.c 2013-10-08 22:29:49.000000000 +0000 +++ gcc-4.8.2/gcc/cp/semantics.c 2014-03-30 20:21:40.647595228 +0000 @@ -2501,7 +2501,8 @@ tree decl; decl = fname_decl (input_location, C_RID_CODE (id), id); - if (processing_template_decl && current_function_decl) + if (processing_template_decl && current_function_decl + && decl != error_mark_node) decl = DECL_NAME (decl); return decl; } @@ -3853,7 +3854,7 @@ linkage of all functions, and as that causes writes to the data mapped in from the PCH file, it's advantageous to mark the functions at this point. */ - if (!DECL_IMPLICIT_INSTANTIATION (fn)) + if (!DECL_IMPLICIT_INSTANTIATION (fn) || DECL_DEFAULTED_FN (fn)) { /* This function must have external linkage, as otherwise DECL_INTERFACE_KNOWN would have been @@ -4291,7 +4292,8 @@ error ("%qE has invalid type for %", t); remove = true; } - else if (FLOAT_TYPE_P (TREE_TYPE (t))) + else if (FLOAT_TYPE_P (TREE_TYPE (t)) + || TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) { enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c); switch (r_code) @@ -4299,10 +4301,26 @@ case PLUS_EXPR: case MULT_EXPR: case MINUS_EXPR: + break; case MIN_EXPR: case MAX_EXPR: + if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) + r_code = ERROR_MARK; break; + case BIT_AND_EXPR: + case BIT_XOR_EXPR: + case BIT_IOR_EXPR: default: + r_code = ERROR_MARK; + break; + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + if (FLOAT_TYPE_P (TREE_TYPE (t))) + r_code = ERROR_MARK; + break; + } + if (r_code == ERROR_MARK) + { error ("%qE has invalid type for %", t, operator_name_info[r_code].name); remove = true; @@ -5059,7 +5077,7 @@ } stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt); } - add_stmt (stmt); + finish_expr_stmt (stmt); } void @@ -7543,7 +7561,7 @@ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); - if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type)) + if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type)) return fold_build3_loc (loc, BIT_FIELD_REF, type, op00, part_width, index); @@ -9481,7 +9499,14 @@ /* In unevaluated context this isn't an odr-use, so just return the nearest 'this'. */ if (cp_unevaluated_operand) - return lookup_name (this_identifier); + { + /* In an NSDMI the fake 'this' pointer that we're using for + parsing is in scope_chain. */ + if (LAMBDA_EXPR_EXTRA_SCOPE (lambda) + && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (lambda)) == FIELD_DECL) + return scope_chain->x_current_class_ptr; + return lookup_name (this_identifier); + } /* Try to default capture 'this' if we can. */ if (!this_capture diff -Naur gcc-4.8.2.orig/gcc/cp/typeck.c gcc-4.8.2/gcc/cp/typeck.c --- gcc-4.8.2.orig/gcc/cp/typeck.c 2013-07-09 17:52:34.000000000 +0000 +++ gcc-4.8.2/gcc/cp/typeck.c 2014-03-30 20:21:40.647595228 +0000 @@ -4103,6 +4103,11 @@ case TRUTH_ORIF_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: + if (TREE_CODE (type0) == VECTOR_TYPE || TREE_CODE (type1) == VECTOR_TYPE) + { + sorry ("logical operation on vector type"); + return error_mark_node; + } result_type = boolean_type_node; break; @@ -5010,7 +5015,10 @@ cp_truthvalue_conversion (tree expr) { tree type = TREE_TYPE (expr); - if (TYPE_PTRDATAMEM_P (type)) + if (TYPE_PTRDATAMEM_P (type) + /* Avoid ICE on invalid use of non-static member function. */ + || (TREE_CODE (expr) == FUNCTION_DECL + && DECL_NONSTATIC_MEMBER_FUNCTION_P (expr))) return build_binary_op (EXPR_LOCATION (expr), NE_EXPR, expr, nullptr_node, 1); else if (TYPE_PTR_P (type) || TYPE_PTRMEMFUNC_P (type)) @@ -5588,7 +5596,9 @@ inc = cxx_sizeof_nowarn (TREE_TYPE (argtype)); } else - inc = integer_one_node; + inc = (TREE_CODE (argtype) == VECTOR_TYPE + ? build_one_cst (argtype) + : integer_one_node); inc = cp_convert (argtype, inc, complain); @@ -7194,8 +7204,7 @@ side effect associated with any single compound assignment operator. -- end note ] */ lhs = stabilize_reference (lhs); - if (TREE_SIDE_EFFECTS (rhs)) - rhs = mark_rvalue_use (rhs); + rhs = rvalue (rhs); rhs = stabilize_expr (rhs, &init); newrhs = cp_build_binary_op (input_location, modifycode, lhs, rhs, @@ -7611,7 +7620,7 @@ /* Handle null pointer to member function conversions. */ if (null_ptr_cst_p (pfn)) { - pfn = build_c_cast (input_location, type, pfn); + pfn = cp_build_c_cast (type, pfn, complain); return build_ptrmemfunc1 (to_type, integer_zero_node, pfn); diff -Naur gcc-4.8.2.orig/gcc/cse.c gcc-4.8.2/gcc/cse.c --- gcc-4.8.2.orig/gcc/cse.c 2013-02-07 08:07:04.000000000 +0000 +++ gcc-4.8.2/gcc/cse.c 2014-03-30 20:21:40.647595228 +0000 @@ -1824,7 +1824,7 @@ } } -/* Function called for each rtx to check whether true dependence exist. */ +/* Function called for each rtx to check whether an anti dependence exist. */ struct check_dependence_data { enum machine_mode mode; @@ -1837,7 +1837,7 @@ { struct check_dependence_data *d = (struct check_dependence_data *) data; if (*x && MEM_P (*x)) - return canon_true_dependence (d->exp, d->mode, d->addr, *x, NULL_RTX); + return canon_anti_dependence (*x, true, d->exp, d->mode, d->addr); else return 0; } @@ -6081,6 +6081,18 @@ validate_change (object, &XEXP (x, 0), new_rtx, 0); return x; } + + case UNSIGNED_FLOAT: + { + rtx new_rtx = cse_process_notes (XEXP (x, 0), object, changed); + /* We don't substitute negative VOIDmode constants into these rtx, + since they would impede folding. */ + if (GET_MODE (new_rtx) != VOIDmode + || (CONST_INT_P (new_rtx) && INTVAL (new_rtx) >= 0) + || (CONST_DOUBLE_P (new_rtx) && CONST_DOUBLE_HIGH (new_rtx) >= 0)) + validate_change (object, &XEXP (x, 0), new_rtx, 0); + return x; + } case REG: i = REG_QTY (REGNO (x)); diff -Naur gcc-4.8.2.orig/gcc/cselib.c gcc-4.8.2/gcc/cselib.c --- gcc-4.8.2.orig/gcc/cselib.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/cselib.c 2014-03-30 20:21:40.650928664 +0000 @@ -2260,8 +2260,8 @@ continue; } if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS) - && ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), - mem_addr, x, NULL_RTX)) + && ! canon_anti_dependence (x, false, mem_rtx, + GET_MODE (mem_rtx), mem_addr)) { has_mem = true; num_mems++; diff -Naur gcc-4.8.2.orig/gcc/doc/extend.texi gcc-4.8.2/gcc/doc/extend.texi --- gcc-4.8.2.orig/gcc/doc/extend.texi 2013-10-07 07:45:12.000000000 +0000 +++ gcc-4.8.2/gcc/doc/extend.texi 2014-03-30 20:21:40.650928664 +0000 @@ -3121,6 +3121,17 @@ prologue used in Win32 API functions in Microsoft Windows XP Service Pack 2 and newer. +@item hotpatch [(@var{prologue-halfwords})] +@cindex @code{hotpatch} attribute + +On S/390 System z targets, you can use this function attribute to +make GCC generate a ``hot-patching'' function prologue. The +@code{hotpatch} has no effect on funtions that are explicitly +inline. If the @option{-mhotpatch} or @option{-mno-hotpatch} +command-line option is used at the same time, the @code{hotpatch} +attribute takes precedence. If an argument is given, the maximum +allowed value is 1000000. + @item naked @cindex function without a prologue/epilogue code Use this attribute on the ARM, AVR, MCORE, RX and SPU ports to indicate that diff -Naur gcc-4.8.2.orig/gcc/doc/invoke.texi gcc-4.8.2/gcc/doc/invoke.texi --- gcc-4.8.2.orig/gcc/doc/invoke.texi 2013-06-19 19:55:50.000000000 +0000 +++ gcc-4.8.2/gcc/doc/invoke.texi 2014-03-30 20:21:40.654262119 +0000 @@ -161,7 +161,7 @@ -pipe -pass-exit-codes @gol -x @var{language} -v -### --help@r{[}=@var{class}@r{[},@dots{}@r{]]} --target-help @gol --version -wrapper @@@var{file} -fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg} @gol --fdump-ada-spec@r{[}-slim@r{]} -fada-spec-parent=@var{arg} -fdump-go-spec=@var{file}} +-fdump-ada-spec@r{[}-slim@r{]} -fada-spec-parent=@var{unit} -fdump-go-spec=@var{file}} @item C Language Options @xref{C Dialect Options,,Options Controlling C Dialect}. @@ -879,7 +879,8 @@ -msmall-exec -mno-small-exec -mmvcle -mno-mvcle @gol -m64 -m31 -mdebug -mno-debug -mesa -mzarch @gol -mtpf-trace -mno-tpf-trace -mfused-madd -mno-fused-madd @gol --mwarn-framesize -mwarn-dynamicstack -mstack-size -mstack-guard} +-mwarn-framesize -mwarn-dynamicstack -mstack-size -mstack-guard @gol +-mhotpatch[=@var{halfwords}] -mno-hotpatch} @emph{Score Options} @gccoptlist{-meb -mel @gol @@ -928,7 +929,7 @@ -mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol -mcbcond -mno-cbcond @gol -mfmaf -mno-fmaf -mpopc -mno-popc @gol --mfix-at697f} +-mfix-at697f -mfix-ut699} @emph{SPU Options} @gccoptlist{-mwarn-reloc -merror-reloc @gol @@ -1460,11 +1461,18 @@ for the plugin called @var{name}. @item -fdump-ada-spec@r{[}-slim@r{]} -For C and C++ source and include files, generate corresponding Ada -specs. @xref{Generating Ada Bindings for C and C++ headers,,, gnat_ugn, +@opindex fdump-ada-spec +For C and C++ source and include files, generate corresponding Ada specs. +@xref{Generating Ada Bindings for C and C++ headers,,, gnat_ugn, GNAT User's Guide}, which provides detailed documentation on this feature. +@item -fada-spec-parent=@var{unit} +@opindex fada-spec-parent +In conjunction with @option{-fdump-ada-spec@r{[}-slim@r{]}} above, generate +Ada specs as child units of parent @var{unit}. + @item -fdump-go-spec=@var{file} +@opindex fdump-go-spec For input files in any language, generate corresponding Go declarations in @var{file}. This generates Go @code{const}, @code{type}, @code{var}, and @code{func} declarations which may be a @@ -11241,11 +11249,32 @@ big-endian ARM processors generated by versions of the compiler prior to 2.8. This option is now deprecated. -@item -mcpu=@var{name} -@opindex mcpu -This specifies the name of the target ARM processor. GCC uses this name -to determine what kind of instructions it can emit when generating -assembly code. Permissible names are: @samp{arm2}, @samp{arm250}, +@item -march=@var{name} +@opindex march +This specifies the name of the target ARM architecture. GCC uses this +name to determine what kind of instructions it can emit when generating +assembly code. This option can be used in conjunction with or instead +of the @option{-mcpu=} option. Permissible names are: @samp{armv2}, +@samp{armv2a}, @samp{armv3}, @samp{armv3m}, @samp{armv4}, @samp{armv4t}, +@samp{armv5}, @samp{armv5t}, @samp{armv5e}, @samp{armv5te}, +@samp{armv6}, @samp{armv6j}, +@samp{armv6t2}, @samp{armv6z}, @samp{armv6zk}, @samp{armv6-m}, +@samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m}, @samp{armv7e-m} +@samp{armv8-a}, +@samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}. + +@option{-march=native} causes the compiler to auto-detect the architecture +of the build computer. At present, this feature is only supported on +Linux, and not all architectures are recognized. If the auto-detect is +unsuccessful the option has no effect. + +@item -mtune=@var{name} +@opindex mtune +This option specifies the name of the target ARM processor for +which GCC should tune the performance of the code. +For some ARM implementations better performance can be obtained by using +this option. +Permissible names are: @samp{arm2}, @samp{arm250}, @samp{arm3}, @samp{arm6}, @samp{arm60}, @samp{arm600}, @samp{arm610}, @samp{arm620}, @samp{arm7}, @samp{arm7m}, @samp{arm7d}, @samp{arm7dm}, @samp{arm7di}, @samp{arm7dmi}, @samp{arm70}, @samp{arm700}, @@ -11273,27 +11302,6 @@ @samp{fa526}, @samp{fa626}, @samp{fa606te}, @samp{fa626te}, @samp{fmp626}, @samp{fa726te}. - -@option{-mcpu=generic-@var{arch}} is also permissible, and is -equivalent to @option{-march=@var{arch} -mtune=generic-@var{arch}}. -See @option{-mtune} for more information. - -@option{-mcpu=native} causes the compiler to auto-detect the CPU -of the build computer. At present, this feature is only supported on -Linux, and not all architectures are recognized. If the auto-detect is -unsuccessful the option has no effect. - -@item -mtune=@var{name} -@opindex mtune -This option is very similar to the @option{-mcpu=} option, except that -instead of specifying the actual target processor type, and hence -restricting which instructions can be used, it specifies that GCC should -tune the performance of the code as if the target were of the type -specified in this option, but still choosing the instructions it -generates based on the CPU specified by a @option{-mcpu=} option. -For some ARM implementations better performance can be obtained by using -this option. - @option{-mtune=generic-@var{arch}} specifies that GCC should tune the performance for a blend of processors within architecture @var{arch}. The aim is to generate code that run well on the current most popular @@ -11306,21 +11314,23 @@ Linux, and not all architectures are recognized. If the auto-detect is unsuccessful the option has no effect. -@item -march=@var{name} -@opindex march -This specifies the name of the target ARM architecture. GCC uses this -name to determine what kind of instructions it can emit when generating -assembly code. This option can be used in conjunction with or instead -of the @option{-mcpu=} option. Permissible names are: @samp{armv2}, -@samp{armv2a}, @samp{armv3}, @samp{armv3m}, @samp{armv4}, @samp{armv4t}, -@samp{armv5}, @samp{armv5t}, @samp{armv5e}, @samp{armv5te}, -@samp{armv6}, @samp{armv6j}, -@samp{armv6t2}, @samp{armv6z}, @samp{armv6zk}, @samp{armv6-m}, -@samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m}, -@samp{armv8-a}, -@samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}. +@item -mcpu=@var{name} +@opindex mcpu +This specifies the name of the target ARM processor. GCC uses this name +to derive the name of the target ARM architecture (as if specified +by @option{-march}) and the ARM processor type for which to tune for +performance (as if specified by @option{-mtune}). Where this option +is used in conjunction with @option{-march} or @option{-mtune}, +those options take precedence over the appropriate part of this option. -@option{-march=native} causes the compiler to auto-detect the architecture +Permissible names for this option are the same as those for +@option{-mtune}. + +@option{-mcpu=generic-@var{arch}} is also permissible, and is +equivalent to @option{-march=@var{arch} -mtune=generic-@var{arch}}. +See @option{-mtune} for more information. + +@option{-mcpu=native} causes the compiler to auto-detect the CPU of the build computer. At present, this feature is only supported on Linux, and not all architectures are recognized. If the auto-detect is unsuccessful the option has no effect. @@ -11409,8 +11419,11 @@ @item -mpic-register=@var{reg} @opindex mpic-register -Specify the register to be used for PIC addressing. The default is R10 -unless stack-checking is enabled, when R9 is used. +Specify the register to be used for PIC addressing. +For standard PIC base case, the default will be any suitable register +determined by compiler. For single PIC base case, the default is +@samp{R9} if target is EABI based or stack-checking is enabled, +otherwise the default is @samp{R10}. @item -mpoke-function-name @opindex mpoke-function-name @@ -18449,6 +18462,21 @@ In order to be efficient the extra code makes the assumption that the stack starts at an address aligned to the value given by @var{stack-size}. The @var{stack-guard} option can only be used in conjunction with @var{stack-size}. + +@item -mhotpatch[=@var{halfwords}] +@itemx -mno-hotpatch +@opindex mhotpatch +If the hotpatch option is enabled, a ``hot-patching'' function +prologue is generated for all functions in the compilation unit. +The funtion label is prepended with the given number of two-byte +Nop instructions (@var{halfwords}, maximum 1000000) or 12 Nop +instructions if no argument is present. Functions with a +hot-patching prologue are never inlined automatically, and a +hot-patching prologue is never generated for functions functions +that are explicitly inline. + +This option can be overridden for individual functions with the +@code{hotpatch} attribute. @end table @node Score Options @@ -19133,10 +19161,10 @@ Set the instruction set, register set, and instruction scheduling parameters for machine type @var{cpu_type}. Supported values for @var{cpu_type} are @samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{hypersparc}, -@samp{leon}, @samp{sparclite}, @samp{f930}, @samp{f934}, @samp{sparclite86x}, -@samp{sparclet}, @samp{tsc701}, @samp{v9}, @samp{ultrasparc}, -@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3}, -and @samp{niagara4}. +@samp{leon}, @samp{leon3}, @samp{sparclite}, @samp{f930}, @samp{f934}, +@samp{sparclite86x}, @samp{sparclet}, @samp{tsc701}, @samp{v9}, +@samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, +@samp{niagara3} and @samp{niagara4}. Native Solaris and GNU/Linux toolchains also support the value @samp{native}, which selects the best architecture option for the host processor. @@ -19155,7 +19183,7 @@ cypress @item v8 -supersparc, hypersparc, leon +supersparc, hypersparc, leon, leon3 @item sparclite f930, f934, sparclite86x @@ -19217,10 +19245,11 @@ The same values for @option{-mcpu=@var{cpu_type}} can be used for @option{-mtune=@var{cpu_type}}, but the only useful values are those that select a particular CPU implementation. Those are @samp{cypress}, -@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{f930}, @samp{f934}, -@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, @samp{ultrasparc3}, -@samp{niagara}, @samp{niagara2}, @samp{niagara3} and @samp{niagara4}. With -native Solaris and GNU/Linux toolchains, @samp{native} can also be used. +@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{leon3}, @samp{f930}, +@samp{f934}, @samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, +@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3} and +@samp{niagara4}. With native Solaris and GNU/Linux toolchains, @samp{native} +can also be used. @item -mv8plus @itemx -mno-v8plus @@ -19289,6 +19318,11 @@ @opindex mfix-at697f Enable the documented workaround for the single erratum of the Atmel AT697F processor (which corresponds to erratum #13 of the AT697E processor). + +@item -mfix-ut699 +@opindex mfix-ut699 +Enable the documented workarounds for the floating-point errata and the data +cache nullify errata of the UT699 processor. @end table These @samp{-m} options are supported in addition to the above diff -Naur gcc-4.8.2.orig/gcc/expr.c gcc-4.8.2/gcc/expr.c --- gcc-4.8.2.orig/gcc/expr.c 2013-08-29 18:37:46.000000000 +0000 +++ gcc-4.8.2/gcc/expr.c 2014-03-30 20:21:40.654262119 +0000 @@ -1994,12 +1994,14 @@ HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1)); enum machine_mode mode = GET_MODE (tmps[i]); unsigned int bytelen = GET_MODE_SIZE (mode); - unsigned int adj_bytelen = bytelen; + unsigned int adj_bytelen; rtx dest = dst; /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) adj_bytelen = ssize - bytepos; + else + adj_bytelen = bytelen; if (GET_CODE (dst) == CONCAT) { @@ -2040,6 +2042,7 @@ } } + /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) { /* store_bit_field always takes its value from the lsb. @@ -2057,16 +2060,22 @@ tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i], shift, tmps[i], 0); } - bytelen = adj_bytelen; + + /* Make sure not to write past the end of the struct. */ + store_bit_field (dest, + adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, + bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT - 1, + VOIDmode, tmps[i]); } /* Optimize the access just a bit. */ - if (MEM_P (dest) - && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) - || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) - && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 - && bytelen == GET_MODE_SIZE (mode)) + else if (MEM_P (dest) + && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) + || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) + && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 + && bytelen == GET_MODE_SIZE (mode)) emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]); + else store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, 0, 0, mode, tmps[i]); @@ -3602,12 +3611,21 @@ into a new pseudo. This constant may be used in different modes, and if not, combine will put things back together for us. */ trunc_y = force_reg (srcmode, trunc_y); - emit_unop_insn (ic, x, trunc_y, UNKNOWN); + + /* If x is a hard register, perform the extension into a pseudo, + so that e.g. stack realignment code is aware of it. */ + rtx target = x; + if (REG_P (x) && HARD_REGISTER_P (x)) + target = gen_reg_rtx (dstmode); + + emit_unop_insn (ic, target, trunc_y, UNKNOWN); last_insn = get_last_insn (); - if (REG_P (x)) + if (REG_P (target)) set_unique_reg_note (last_insn, REG_EQUAL, y); + if (target != x) + return emit_move_insn (x, target); return last_insn; } @@ -4551,19 +4569,19 @@ - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); /* If the adjustment is larger than bitpos, we would have a negative bit - position for the lower bound and this may wreak havoc later. This can - occur only if we have a non-null offset, so adjust offset and bitpos - to make the lower bound non-negative. */ + position for the lower bound and this may wreak havoc later. Adjust + offset and bitpos to make the lower bound non-negative in that case. */ if (bitoffset > *bitpos) { HOST_WIDE_INT adjust = bitoffset - *bitpos; - gcc_assert ((adjust % BITS_PER_UNIT) == 0); - gcc_assert (*offset != NULL_TREE); *bitpos += adjust; - *offset - = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT)); + if (*offset == NULL_TREE) + *offset = size_int (-adjust / BITS_PER_UNIT); + else + *offset + = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT)); *bitstart = 0; } else @@ -4668,8 +4686,7 @@ expand_insn (icode, 2, ops); } else - store_bit_field (mem, GET_MODE_BITSIZE (mode), - 0, 0, 0, mode, reg); + store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg); return; } @@ -4698,6 +4715,15 @@ tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, &unsignedp, &volatilep, true); + /* Make sure bitpos is not negative, it can wreak havoc later. */ + if (bitpos < 0) + { + gcc_assert (offset == NULL_TREE); + offset = size_int (bitpos >> (BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT))); + bitpos &= BITS_PER_UNIT - 1; + } + if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset); diff -Naur gcc-4.8.2.orig/gcc/fold-const.c gcc-4.8.2/gcc/fold-const.c --- gcc-4.8.2.orig/gcc/fold-const.c 2013-09-30 20:16:14.000000000 +0000 +++ gcc-4.8.2/gcc/fold-const.c 2014-03-30 20:21:40.657595568 +0000 @@ -2664,10 +2664,11 @@ case COMPONENT_REF: /* Handle operand 2 the same as for ARRAY_REF. Operand 0 may be NULL when we're called to compare MEM_EXPRs. */ - if (!OP_SAME_WITH_NULL (0)) + if (!OP_SAME_WITH_NULL (0) + || !OP_SAME (1)) return 0; flags &= ~OEP_CONSTANT_ADDRESS_OF; - return OP_SAME (1) && OP_SAME_WITH_NULL (2); + return OP_SAME_WITH_NULL (2); case BIT_FIELD_REF: if (!OP_SAME (0)) @@ -4920,12 +4921,16 @@ int in0_p, in1_p, in_p; tree low0, low1, low, high0, high1, high; bool strict_overflow_p = false; - tree lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p); - tree rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p); - tree tem; + tree tem, lhs, rhs; const char * const warnmsg = G_("assuming signed overflow does not occur " "when simplifying range test"); + if (!INTEGRAL_TYPE_P (type)) + return 0; + + lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p); + rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p); + /* If this is an OR operation, invert both sides; we will invert again at the end. */ if (or_op) @@ -10927,6 +10932,13 @@ fold_build2_loc (loc, MULT_EXPR, type, build_int_cst (type, 2) , arg1)); + /* ((T) (X /[ex] C)) * C cancels out if the conversion is + sign-changing only. */ + if (TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (arg0) == EXACT_DIV_EXPR + && operand_equal_p (arg1, TREE_OPERAND (arg0, 1), 0)) + return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); + strict_overflow_p = false; if (TREE_CODE (arg1) == INTEGER_CST && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE, @@ -16587,7 +16599,7 @@ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); - if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type)) + if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type)) return fold_build3_loc (loc, BIT_FIELD_REF, type, op00, part_width, index); diff -Naur gcc-4.8.2.orig/gcc/fortran/check.c gcc-4.8.2/gcc/fortran/check.c --- gcc-4.8.2.orig/gcc/fortran/check.c 2013-04-26 19:20:55.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/check.c 2014-03-30 20:21:40.657595568 +0000 @@ -3208,7 +3208,7 @@ "than %d elements", &shape->where, GFC_MAX_DIMENSIONS); return FAILURE; } - else if (shape->expr_type == EXPR_ARRAY) + else if (shape->expr_type == EXPR_ARRAY && gfc_is_constant_expr (shape)) { gfc_expr *e; int i, extent; diff -Naur gcc-4.8.2.orig/gcc/fortran/class.c gcc-4.8.2/gcc/fortran/class.c --- gcc-4.8.2.orig/gcc/fortran/class.c 2013-01-27 07:09:06.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/class.c 2014-03-30 20:21:40.657595568 +0000 @@ -2486,7 +2486,7 @@ return NULL; /* Sometimes the typespec is passed from a single call. */ - if (ts->type == BT_DERIVED) + if (ts->type == BT_DERIVED || ts->type == BT_CLASS) return gfc_find_derived_vtab (ts->u.derived); /* Find the top-level namespace. */ diff -Naur gcc-4.8.2.orig/gcc/fortran/decl.c gcc-4.8.2/gcc/fortran/decl.c --- gcc-4.8.2.orig/gcc/fortran/decl.c 2013-02-02 09:50:58.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/decl.c 2014-03-30 20:21:40.657595568 +0000 @@ -510,9 +510,7 @@ free (newdata); return MATCH_ERROR; } - - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (gfc_current_ns->proc_name); /* Mark the variable as having appeared in a data statement. */ if (gfc_add_data (&sym->attr, sym->name, &sym->declared_at) == FAILURE) @@ -571,9 +569,7 @@ gfc_error ("DATA statement at %C is not allowed in a PURE procedure"); return MATCH_ERROR; } - - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (gfc_current_ns->proc_name); return MATCH_YES; @@ -1737,6 +1733,7 @@ "a PURE procedure"); return MATCH_ERROR; } + gfc_unset_implicit_pure (gfc_current_ns->proc_name); /* Match NULL() initialization. */ m = gfc_match_null (init); @@ -2045,6 +2042,10 @@ m = MATCH_ERROR; } + if (current_attr.flavor != FL_PARAMETER + && gfc_state_stack->state != COMP_DERIVED) + gfc_unset_implicit_pure (gfc_current_ns->proc_name); + if (m != MATCH_YES) goto cleanup; } @@ -5069,7 +5070,14 @@ if (gfc_add_proc (&c->attr, name, NULL) == FAILURE) return MATCH_ERROR; - c->tb = tb; + if (num == 1) + c->tb = tb; + else + { + c->tb = XCNEW (gfc_typebound_proc); + c->tb->where = gfc_current_locus; + *c->tb = *tb; + } /* Set interface. */ if (proc_if != NULL) @@ -7384,6 +7392,7 @@ /* Check a derived type that is being extended. */ + static gfc_symbol* check_extended_derived_type (char *name) { @@ -7395,14 +7404,15 @@ return NULL; } + extended = gfc_find_dt_in_generic (extended); + + /* F08:C428. */ if (!extended) { - gfc_error ("No such symbol in TYPE definition at %C"); + gfc_error ("Symbol '%s' at %C has not been previously defined", name); return NULL; } - extended = gfc_find_dt_in_generic (extended); - if (extended->attr.flavor != FL_DERIVED) { gfc_error ("'%s' in EXTENDS expression at %C is not a " diff -Naur gcc-4.8.2.orig/gcc/fortran/dump-parse-tree.c gcc-4.8.2/gcc/fortran/dump-parse-tree.c --- gcc-4.8.2.orig/gcc/fortran/dump-parse-tree.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/dump-parse-tree.c 2014-03-30 20:21:40.657595568 +0000 @@ -110,7 +110,8 @@ break; case BT_CHARACTER: - show_expr (ts->u.cl->length); + if (ts->u.cl) + show_expr (ts->u.cl->length); fprintf(dumpfile, " %d", ts->kind); break; diff -Naur gcc-4.8.2.orig/gcc/fortran/expr.c gcc-4.8.2/gcc/fortran/expr.c --- gcc-4.8.2.orig/gcc/fortran/expr.c 2013-04-26 19:20:55.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/expr.c 2014-03-30 20:21:40.660929013 +0000 @@ -3555,11 +3555,13 @@ return FAILURE; } - if (!gfc_compare_interfaces (s2, s1, name, 0, 1, - err, sizeof(err), NULL, NULL)) + /* Check F2008Cor2, C729. */ + if (!s2->attr.intrinsic && s2->attr.if_source == IFSRC_UNKNOWN + && !s2->attr.external && !s2->attr.subroutine && !s2->attr.function) { - gfc_error ("Interface mismatch in procedure pointer assignment " - "at %L: %s", &rvalue->where, err); + gfc_error ("Procedure pointer target '%s' at %L must be either an " + "intrinsic, host or use associated, referenced or have " + "the EXTERNAL attribute", s2->name, &rvalue->where); return FAILURE; } @@ -3679,8 +3681,7 @@ } if (is_implicit_pure && gfc_impure_variable (rvalue->symtree->n.sym)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; - + gfc_unset_implicit_pure (gfc_current_ns->proc_name); if (gfc_has_vector_index (rvalue)) { diff -Naur gcc-4.8.2.orig/gcc/fortran/frontend-passes.c gcc-4.8.2/gcc/fortran/frontend-passes.c --- gcc-4.8.2.orig/gcc/fortran/frontend-passes.c 2013-04-22 14:07:29.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/frontend-passes.c 2014-03-30 20:21:40.660929013 +0000 @@ -623,12 +623,35 @@ to insert statements as needed. */ static int -cfe_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) +cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) { current_code = c; inserted_block = NULL; changed_statement = NULL; + + /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs + and allocation on assigment are prohibited inside WHERE, and finally + masking an expression would lead to wrong-code when replacing + + WHERE (a>0) + b = sum(foo(a) + foo(a)) + END WHERE + + with + + WHERE (a > 0) + tmp = foo(a) + b = sum(tmp + tmp) + END WHERE +*/ + + if ((*c)->op == EXEC_WHERE) + { + *walk_subtrees = 0; + return 0; + } + + return 0; } @@ -1214,7 +1237,9 @@ /* Replace A // B < A // C with B < C, and A // B < C // B with A < C. */ if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER + && op1->expr_type == EXPR_OP && op1->value.op.op == INTRINSIC_CONCAT + && op2->expr_type == EXPR_OP && op2->value.op.op == INTRINSIC_CONCAT) { gfc_expr *op1_left = op1->value.op.op1; diff -Naur gcc-4.8.2.orig/gcc/fortran/gfortran.h gcc-4.8.2/gcc/fortran/gfortran.h --- gcc-4.8.2.orig/gcc/fortran/gfortran.h 2013-03-03 17:34:42.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/gfortran.h 2014-03-30 20:21:40.660929013 +0000 @@ -2830,6 +2830,7 @@ int gfc_impure_variable (gfc_symbol *); int gfc_pure (gfc_symbol *); int gfc_implicit_pure (gfc_symbol *); +void gfc_unset_implicit_pure (gfc_symbol *); int gfc_elemental (gfc_symbol *); gfc_try gfc_resolve_iterator (gfc_iterator *, bool, bool); gfc_try find_forall_index (gfc_expr *, gfc_symbol *, int); diff -Naur gcc-4.8.2.orig/gcc/fortran/interface.c gcc-4.8.2/gcc/fortran/interface.c --- gcc-4.8.2.orig/gcc/fortran/interface.c 2013-05-31 18:10:03.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/interface.c 2014-03-30 20:21:40.660929013 +0000 @@ -1245,7 +1245,8 @@ return FAILURE; } - if (r1->ts.u.cl->length) + if (s1->ts.u.cl && s1->ts.u.cl->length + && s2->ts.u.cl && s2->ts.u.cl->length) { int compval = gfc_dep_compare_expr (r1->ts.u.cl->length, r2->ts.u.cl->length); @@ -1367,8 +1368,8 @@ if (s1->attr.function && s2->attr.function) { /* If both are functions, check result characteristics. */ - if (check_result_characteristics (s1, s2, errmsg, err_len) - == FAILURE) + if (check_result_characteristics (s1, s2, errmsg, err_len) == FAILURE + || check_result_characteristics (s2, s1, errmsg, err_len) == FAILURE) return 0; } diff -Naur gcc-4.8.2.orig/gcc/fortran/intrinsic.c gcc-4.8.2/gcc/fortran/intrinsic.c --- gcc-4.8.2.orig/gcc/fortran/intrinsic.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/intrinsic.c 2014-03-30 20:21:40.660929013 +0000 @@ -4229,13 +4229,16 @@ c->resolved_sym->attr.elemental = isym->elemental; } - if (gfc_pure (NULL) && !isym->pure) + if (!isym->pure && gfc_pure (NULL)) { gfc_error ("Subroutine call to intrinsic '%s' at %L is not PURE", name, &c->loc); return MATCH_ERROR; } + if (!isym->pure) + gfc_unset_implicit_pure (NULL); + c->resolved_sym->attr.noreturn = isym->noreturn; return MATCH_YES; diff -Naur gcc-4.8.2.orig/gcc/fortran/invoke.texi gcc-4.8.2/gcc/fortran/invoke.texi --- gcc-4.8.2.orig/gcc/fortran/invoke.texi 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/invoke.texi 2014-03-30 20:21:40.660929013 +0000 @@ -982,11 +982,12 @@ into internal representation. Only really useful for debugging the GNU Fortran compiler itself. -@item -fdump-optimized-tree +@item -fdump-fortran-optimized @opindex @code{fdump-fortran-optimized} Output the parse tree after front-end optimization. Only really useful for debugging the GNU Fortran compiler itself. +@item -fdump-parse-tree @opindex @code{fdump-parse-tree} Output the internal parse tree after translating the source program into internal representation. Only really useful for debugging the diff -Naur gcc-4.8.2.orig/gcc/fortran/io.c gcc-4.8.2/gcc/fortran/io.c --- gcc-4.8.2.orig/gcc/fortran/io.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/io.c 2014-03-30 20:21:40.660929013 +0000 @@ -1309,7 +1309,8 @@ return MATCH_ERROR; } - if (gfc_pure (NULL) && gfc_impure_variable (result->symtree->n.sym)) + bool impure = gfc_impure_variable (result->symtree->n.sym); + if (impure && gfc_pure (NULL)) { gfc_error ("Variable %s cannot be assigned in PURE procedure at %C", tag->name); @@ -1317,8 +1318,8 @@ return MATCH_ERROR; } - if (gfc_implicit_pure (NULL) && gfc_impure_variable (result->symtree->n.sym)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + if (impure) + gfc_unset_implicit_pure (NULL); *v = result; return MATCH_YES; @@ -1838,8 +1839,7 @@ goto cleanup; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); warn = (open->err || open->iostat) ? true : false; @@ -2251,8 +2251,7 @@ goto cleanup; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); warn = (close->iostat || close->err) ? true : false; @@ -2419,8 +2418,7 @@ goto cleanup; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); new_st.op = op; new_st.ext.filepos = fp; @@ -3276,9 +3274,8 @@ "an internal file in a PURE procedure", io_kind_name (k)); - if (gfc_implicit_pure (NULL) && (k == M_READ || k == M_WRITE)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; - + if (k == M_READ || k == M_WRITE) + gfc_unset_implicit_pure (NULL); } if (k != M_READ) @@ -3809,8 +3806,7 @@ return MATCH_ERROR; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); return MATCH_YES; } @@ -3969,8 +3965,7 @@ return MATCH_ERROR; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); new_st.block = gfc_get_code (); new_st.block->op = EXEC_IOLENGTH; @@ -4023,8 +4018,7 @@ goto cleanup; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); if (inquire->id != NULL && inquire->pending == NULL) { @@ -4212,8 +4206,7 @@ goto cleanup; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); new_st.op = EXEC_WAIT; new_st.ext.wait = wait; diff -Naur gcc-4.8.2.orig/gcc/fortran/match.c gcc-4.8.2/gcc/fortran/match.c --- gcc-4.8.2.orig/gcc/fortran/match.c 2013-08-24 09:12:21.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/match.c 2014-03-30 20:21:40.664262457 +0000 @@ -1753,8 +1753,7 @@ return MATCH_ERROR; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); if (gfc_notify_std (GFC_STD_F2008, "CRITICAL statement at %C") == FAILURE) @@ -2683,8 +2682,7 @@ goto cleanup; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); if (st == ST_STOP && gfc_find_state (COMP_CRITICAL) == SUCCESS) { @@ -2824,8 +2822,7 @@ return MATCH_ERROR; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); if (gfc_option.coarray == GFC_FCOARRAY_NONE) { @@ -3020,8 +3017,7 @@ return MATCH_ERROR; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); if (gfc_notify_std (GFC_STD_F2008, "SYNC statement at %C") == FAILURE) @@ -3500,15 +3496,15 @@ if (gfc_check_do_variable (tail->expr->symtree)) goto cleanup; - if (gfc_pure (NULL) && gfc_impure_variable (tail->expr->symtree->n.sym)) + bool impure = gfc_impure_variable (tail->expr->symtree->n.sym); + if (impure && gfc_pure (NULL)) { gfc_error ("Bad allocate-object at %C for a PURE procedure"); goto cleanup; } - if (gfc_implicit_pure (NULL) - && gfc_impure_variable (tail->expr->symtree->n.sym)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + if (impure) + gfc_unset_implicit_pure (NULL); if (tail->expr->ts.deferred) { @@ -3890,14 +3886,15 @@ sym = tail->expr->symtree->n.sym; - if (gfc_pure (NULL) && gfc_impure_variable (sym)) + bool impure = gfc_impure_variable (sym); + if (impure && gfc_pure (NULL)) { gfc_error ("Illegal allocate-object at %C for a PURE procedure"); goto cleanup; } - if (gfc_implicit_pure (NULL) && gfc_impure_variable (sym)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + if (impure) + gfc_unset_implicit_pure (NULL); if (gfc_is_coarray (tail->expr) && gfc_find_state (COMP_DO_CONCURRENT) == SUCCESS) diff -Naur gcc-4.8.2.orig/gcc/fortran/module.c gcc-4.8.2/gcc/fortran/module.c --- gcc-4.8.2.orig/gcc/fortran/module.c 2013-07-28 14:13:17.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/module.c 2014-03-30 20:21:40.664262457 +0000 @@ -386,37 +386,6 @@ } -/* Recursive function to find a pointer within a tree by brute force. */ - -static pointer_info * -fp2 (pointer_info *p, const void *target) -{ - pointer_info *q; - - if (p == NULL) - return NULL; - - if (p->u.pointer == target) - return p; - - q = fp2 (p->left, target); - if (q != NULL) - return q; - - return fp2 (p->right, target); -} - - -/* During reading, find a pointer_info node from the pointer value. - This amounts to a brute-force search. */ - -static pointer_info * -find_pointer2 (void *p) -{ - return fp2 (pi_root, p); -} - - /* Resolve any fixups using a known pointer. */ static void @@ -2522,45 +2491,13 @@ the namespace and is not loaded again. */ static void -mio_component_ref (gfc_component **cp, gfc_symbol *sym) +mio_component_ref (gfc_component **cp) { - char name[GFC_MAX_SYMBOL_LEN + 1]; - gfc_component *q; pointer_info *p; p = mio_pointer_ref (cp); if (p->type == P_UNKNOWN) p->type = P_COMPONENT; - - if (iomode == IO_OUTPUT) - mio_pool_string (&(*cp)->name); - else - { - mio_internal_string (name); - - if (sym && sym->attr.is_class) - sym = sym->components->ts.u.derived; - - /* It can happen that a component reference can be read before the - associated derived type symbol has been loaded. Return now and - wait for a later iteration of load_needed. */ - if (sym == NULL) - return; - - if (sym->components != NULL && p->u.pointer == NULL) - { - /* Symbol already loaded, so search by name. */ - q = gfc_find_component (sym, name, true, true); - - if (q) - associate_integer_pointer (p, q); - } - - /* Make sure this symbol will eventually be loaded. */ - p = find_pointer2 (sym); - if (p->u.rsym.state == UNUSED) - p->u.rsym.state = NEEDED; - } } @@ -2917,7 +2854,7 @@ case REF_COMPONENT: mio_symbol_ref (&r->u.c.sym); - mio_component_ref (&r->u.c.component, r->u.c.sym); + mio_component_ref (&r->u.c.component); break; case REF_SUBSTRING: @@ -3772,7 +3709,9 @@ /* Unlike most other routines, the address of the symbol node is already - fixed on input and the name/module has already been filled in. */ + fixed on input and the name/module has already been filled in. + If you update the symbol format here, don't forget to update read_module + as well (look for "seek to the symbol's component list"). */ static void mio_symbol (gfc_symbol *sym) @@ -3782,6 +3721,7 @@ mio_lparen (); mio_symbol_attribute (&sym->attr); + mio_typespec (&sym->ts); if (sym->ts.type == BT_CLASS) sym->attr.class_ok = 1; @@ -3812,7 +3752,6 @@ /* Note that components are always saved, even if they are supposed to be private. Component access is checked during searching. */ - mio_component_list (&sym->components, sym->attr.vtype); if (sym->components != NULL) @@ -3914,14 +3853,17 @@ } -/* Skip a list between balanced left and right parens. */ +/* Skip a list between balanced left and right parens. + By setting NEST_LEVEL one assumes that a number of NEST_LEVEL opening parens + have been already parsed by hand, and the remaining of the content is to be + skipped here. The default value is 0 (balanced parens). */ static void -skip_list (void) +skip_list (int nest_level = 0) { int level; - level = 0; + level = nest_level; do { switch (parse_atom ()) @@ -4555,7 +4497,6 @@ info->u.rsym.ns = atom_int; get_module_locus (&info->u.rsym.where); - skip_list (); /* See if the symbol has already been loaded by a previous module. If so, we reference the existing symbol and prevent it from @@ -4566,10 +4507,56 @@ if (sym == NULL || (sym->attr.flavor == FL_VARIABLE && info->u.rsym.ns !=1)) - continue; + { + skip_list (); + continue; + } info->u.rsym.state = USED; info->u.rsym.sym = sym; + /* The current symbol has already been loaded, so we can avoid loading + it again. However, if it is a derived type, some of its components + can be used in expressions in the module. To avoid the module loading + failing, we need to associate the module's component pointer indexes + with the existing symbol's component pointers. */ + if (sym->attr.flavor == FL_DERIVED) + { + gfc_component *c; + + /* First seek to the symbol's component list. */ + mio_lparen (); /* symbol opening. */ + skip_list (); /* skip symbol attribute. */ + skip_list (); /* typespec. */ + require_atom (ATOM_INTEGER); /* namespace ref. */ + require_atom (ATOM_INTEGER); /* common ref. */ + skip_list (); /* formal args. */ + /* no value. */ + skip_list (); /* array_spec. */ + require_atom (ATOM_INTEGER); /* result. */ + /* not a cray pointer. */ + + mio_lparen (); /* component list opening. */ + for (c = sym->components; c; c = c->next) + { + pointer_info *p; + const char *comp_name; + int n; + + mio_lparen (); /* component opening. */ + mio_integer (&n); + p = get_integer (n); + if (p->u.pointer == NULL) + associate_integer_pointer (p, c); + mio_pool_string (&comp_name); + gcc_assert (comp_name == c->name); + skip_list (1); /* component end. */ + } + mio_rparen (); /* component list closing. */ + + skip_list (1); /* symbol end. */ + } + else + skip_list (); /* Some symbols do not have a namespace (eg. formal arguments), so the automatic "unique symtree" mechanism must be suppressed diff -Naur gcc-4.8.2.orig/gcc/fortran/parse.c gcc-4.8.2/gcc/fortran/parse.c --- gcc-4.8.2.orig/gcc/fortran/parse.c 2013-04-18 18:20:22.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/parse.c 2014-03-30 20:21:40.664262457 +0000 @@ -550,8 +550,7 @@ return ST_NONE; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); old_locus = gfc_current_locus; diff -Naur gcc-4.8.2.orig/gcc/fortran/primary.c gcc-4.8.2/gcc/fortran/primary.c --- gcc-4.8.2.orig/gcc/fortran/primary.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/primary.c 2014-03-30 20:21:40.664262457 +0000 @@ -2252,7 +2252,7 @@ case EXPR_FUNCTION: gfc_clear_attr (&attr); - if (e->value.function.esym != NULL) + if (e->value.function.esym && e->value.function.esym->result) { gfc_symbol *sym = e->value.function.esym->result; attr = sym->attr; @@ -2540,7 +2540,8 @@ if (parent && !comp) break; - actual = actual->next; + if (actual) + actual = actual->next; } if (build_actual_constructor (&comp_head, &ctor_head, sym) == FAILURE) diff -Naur gcc-4.8.2.orig/gcc/fortran/resolve.c gcc-4.8.2/gcc/fortran/resolve.c --- gcc-4.8.2.orig/gcc/fortran/resolve.c 2013-10-04 16:25:55.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/resolve.c 2014-03-30 20:21:40.667595899 +0000 @@ -1,5 +1,5 @@ /* Perform type resolution on the various structures. - Copyright (C) 2001-2013 Free Software Foundation, Inc. + Copyright (C) 2001-2014 Free Software Foundation, Inc. Contributed by Andy Vaught This file is part of GCC. @@ -1259,9 +1259,10 @@ } /* F2003, C1272 (3). */ - if (gfc_pure (NULL) && cons->expr->expr_type == EXPR_VARIABLE - && (gfc_impure_variable (cons->expr->symtree->n.sym) - || gfc_is_coindexed (cons->expr))) + bool impure = cons->expr->expr_type == EXPR_VARIABLE + && (gfc_impure_variable (cons->expr->symtree->n.sym) + || gfc_is_coindexed (cons->expr)); + if (impure && gfc_pure (NULL)) { t = FAILURE; gfc_error ("Invalid expression in the structure constructor for " @@ -1269,12 +1270,8 @@ comp->name, &cons->expr->where); } - if (gfc_implicit_pure (NULL) - && cons->expr->expr_type == EXPR_VARIABLE - && (gfc_impure_variable (cons->expr->symtree->n.sym) - || gfc_is_coindexed (cons->expr))) - gfc_current_ns->proc_name->attr.implicit_pure = 0; - + if (impure) + gfc_unset_implicit_pure (NULL); } return t; @@ -3295,8 +3292,7 @@ t = FAILURE; } - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); } /* Functions without the RECURSIVE attribution are not allowed to @@ -3361,8 +3357,7 @@ gfc_error ("Subroutine call to '%s' at %L is not PURE", sym->name, &c->loc); - if (gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); } @@ -8705,10 +8700,11 @@ && exp->value.op.op == INTRINSIC_PARENTHESES) exp = exp->value.op.op1; - if (exp && exp->expr_type == EXPR_NULL && exp->ts.type == BT_UNKNOWN) + if (exp && exp->expr_type == EXPR_NULL + && code->ext.dt) { - gfc_error ("NULL intrinsic at %L in data transfer statement requires " - "MOLD=", &exp->where); + gfc_error ("Invalid context for NULL () intrinsic at %L", + &exp->where); return; } @@ -9612,7 +9608,7 @@ if (lhs->expr_type == EXPR_VARIABLE && lhs->symtree->n.sym != gfc_current_ns->proc_name && lhs->symtree->n.sym->ns != gfc_current_ns) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); if (lhs->ts.type == BT_DERIVED && lhs->expr_type == EXPR_VARIABLE @@ -9620,11 +9616,11 @@ && rhs->expr_type == EXPR_VARIABLE && (gfc_impure_variable (rhs->symtree->n.sym) || gfc_is_coindexed (rhs))) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); /* Fortran 2008, C1283. */ if (gfc_is_coindexed (lhs)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + gfc_unset_implicit_pure (NULL); } /* F03:7.4.1.2. */ @@ -11057,7 +11053,7 @@ init_expr = NULL; } if (!init_expr && gfc_option.flag_init_character == GFC_INIT_CHARACTER_ON - && sym->ts.u.cl->length) + && sym->ts.u.cl->length && gfc_option.flag_max_stack_var_size != 0) { gfc_actual_arglist *arg; init_expr = gfc_get_expr (); @@ -11877,6 +11873,7 @@ { gfc_symbol *sym1, *sym2; const char *pass1, *pass2; + gfc_formal_arglist *dummy_args; gcc_assert (t1->specific && t2->specific); gcc_assert (!t1->specific->is_generic); @@ -11899,19 +11896,33 @@ return FAILURE; } - /* Compare the interfaces. */ + /* Determine PASS arguments. */ if (t1->specific->nopass) pass1 = NULL; else if (t1->specific->pass_arg) pass1 = t1->specific->pass_arg; else - pass1 = gfc_sym_get_dummy_args (t1->specific->u.specific->n.sym)->sym->name; + { + dummy_args = gfc_sym_get_dummy_args (t1->specific->u.specific->n.sym); + if (dummy_args) + pass1 = dummy_args->sym->name; + else + pass1 = NULL; + } if (t2->specific->nopass) pass2 = NULL; else if (t2->specific->pass_arg) pass2 = t2->specific->pass_arg; else - pass2 = gfc_sym_get_dummy_args (t2->specific->u.specific->n.sym)->sym->name; + { + dummy_args = gfc_sym_get_dummy_args (t2->specific->u.specific->n.sym); + if (dummy_args) + pass2 = dummy_args->sym->name; + else + pass2 = NULL; + } + + /* Compare the interfaces. */ if (gfc_compare_interfaces (sym1, sym2, sym2->name, !t1->is_operator, 0, NULL, 0, pass1, pass2)) { @@ -12425,9 +12436,6 @@ resolve_bindings_derived = derived; resolve_bindings_result = SUCCESS; - /* Make sure the vtab has been generated. */ - gfc_find_derived_vtab (derived); - if (derived->f2k_derived->tb_sym_root) gfc_traverse_symtree (derived->f2k_derived->tb_sym_root, &resolve_typebound_procedure); @@ -13256,7 +13264,8 @@ if (sym->attr.flavor == FL_UNKNOWN || (sym->attr.flavor == FL_PROCEDURE && !sym->attr.intrinsic && !sym->attr.generic && !sym->attr.external - && sym->attr.if_source == IFSRC_UNKNOWN)) + && sym->attr.if_source == IFSRC_UNKNOWN + && sym->ts.type == BT_UNKNOWN)) { /* If we find that a flavorless symbol is an interface in one of the @@ -14376,6 +14385,33 @@ } +void +gfc_unset_implicit_pure (gfc_symbol *sym) +{ + gfc_namespace *ns; + + if (sym == NULL) + { + /* Check if the current procedure is implicit_pure. Walk up + the procedure list until we find a procedure. */ + for (ns = gfc_current_ns; ns; ns = ns->parent) + { + sym = ns->proc_name; + if (sym == NULL) + return; + + if (sym->attr.flavor == FL_PROCEDURE) + break; + } + } + + if (sym->attr.flavor == FL_PROCEDURE) + sym->attr.implicit_pure = 0; + else + sym->attr.pure = 0; +} + + /* Test whether the current procedure is elemental or not. */ int diff -Naur gcc-4.8.2.orig/gcc/fortran/simplify.c gcc-4.8.2/gcc/fortran/simplify.c --- gcc-4.8.2.orig/gcc/fortran/simplify.c 2013-07-08 19:10:32.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/simplify.c 2014-03-30 20:21:40.667595899 +0000 @@ -5528,7 +5528,7 @@ if (e == &gfc_bad_expr || range_check (e, "SHAPE") == &gfc_bad_expr) { gfc_free_expr (result); - if (t) + if (t == SUCCESS) gfc_clear_shape (shape, source->rank); return &gfc_bad_expr; } @@ -5536,7 +5536,7 @@ gfc_constructor_append_expr (&result->value.constructor, e, NULL); } - if (t) + if (t == SUCCESS) gfc_clear_shape (shape, source->rank); return result; diff -Naur gcc-4.8.2.orig/gcc/fortran/symbol.c gcc-4.8.2/gcc/fortran/symbol.c --- gcc-4.8.2.orig/gcc/fortran/symbol.c 2013-03-03 17:34:42.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/symbol.c 2014-03-30 20:21:40.667595899 +0000 @@ -1110,8 +1110,8 @@ return FAILURE; } - if (s == SAVE_EXPLICIT && gfc_implicit_pure (NULL)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + if (s == SAVE_EXPLICIT) + gfc_unset_implicit_pure (NULL); if (s == SAVE_EXPLICIT && attr->save == SAVE_EXPLICIT) { diff -Naur gcc-4.8.2.orig/gcc/fortran/trans-array.c gcc-4.8.2/gcc/fortran/trans-array.c --- gcc-4.8.2.orig/gcc/fortran/trans-array.c 2013-08-24 12:46:17.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/trans-array.c 2014-03-30 20:21:40.667595899 +0000 @@ -1,5 +1,5 @@ /* Array translation routines - Copyright (C) 2002-2013 Free Software Foundation, Inc. + Copyright (C) 2002-2014 Free Software Foundation, Inc. Contributed by Paul Brook and Steven Bosscher @@ -2487,6 +2487,11 @@ a reference to the value. */ gfc_conv_expr (&se, expr); } + + /* Ensure that a pointer to the string is stored. */ + if (expr->ts.type == BT_CHARACTER) + gfc_conv_string_parameter (&se); + gfc_add_block_to_block (&outer_loop->pre, &se.pre); gfc_add_block_to_block (&outer_loop->post, &se.post); if (gfc_is_class_scalar_expr (expr)) @@ -7940,6 +7945,7 @@ tree size1; tree size2; tree array1; + tree cond_null; tree cond; tree tmp; tree tmp2; @@ -8015,9 +8021,9 @@ jump_label2 = gfc_build_label_decl (NULL_TREE); /* Allocate if data is NULL. */ - cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, + cond_null = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, array1, build_int_cst (TREE_TYPE (array1), 0)); - tmp = build3_v (COND_EXPR, cond, + tmp = build3_v (COND_EXPR, cond_null, build1_v (GOTO_EXPR, jump_label1), build_empty_stmt (input_location)); gfc_add_expr_to_block (&fblock, tmp); @@ -8069,13 +8075,25 @@ tmp = build1_v (LABEL_EXPR, jump_label1); gfc_add_expr_to_block (&fblock, tmp); - size1 = gfc_conv_descriptor_size (desc, expr1->rank); + /* If the lhs has not been allocated, its bounds will not have been + initialized and so its size is set to zero. */ + size1 = gfc_create_var (gfc_array_index_type, NULL); + gfc_init_block (&alloc_block); + gfc_add_modify (&alloc_block, size1, gfc_index_zero_node); + gfc_init_block (&realloc_block); + gfc_add_modify (&realloc_block, size1, + gfc_conv_descriptor_size (desc, expr1->rank)); + tmp = build3_v (COND_EXPR, cond_null, + gfc_finish_block (&alloc_block), + gfc_finish_block (&realloc_block)); + gfc_add_expr_to_block (&fblock, tmp); - /* Get the rhs size. Fix both sizes. */ + /* Get the rhs size and fix it. */ if (expr2) desc2 = rss->info->data.array.descriptor; else desc2 = NULL_TREE; + size2 = gfc_index_one_node; for (n = 0; n < expr2->rank; n++) { @@ -8089,8 +8107,6 @@ gfc_array_index_type, tmp, size2); } - - size1 = gfc_evaluate_now (size1, &fblock); size2 = gfc_evaluate_now (size2, &fblock); cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, diff -Naur gcc-4.8.2.orig/gcc/fortran/trans-decl.c gcc-4.8.2/gcc/fortran/trans-decl.c --- gcc-4.8.2.orig/gcc/fortran/trans-decl.c 2013-03-01 10:24:11.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/trans-decl.c 2014-03-30 20:21:40.667595899 +0000 @@ -1013,6 +1013,10 @@ TREE_STATIC (decl) = 0; DECL_EXTERNAL (decl) = 0; + /* Avoid uninitialized warnings for optional dummy arguments. */ + if (sym->attr.optional) + TREE_NO_WARNING (decl) = 1; + /* We should never get deferred shape arrays here. We used to because of frontend bugs. */ gcc_assert (sym->as->type != AS_DEFERRED); @@ -1358,9 +1362,10 @@ if (sym->attr.flavor == FL_PROCEDURE) { - /* Catch function declarations. Only used for actual parameters, + /* Catch functions. Only used for actual parameters, procedure pointers and procptr initialization targets. */ - if (sym->attr.external || sym->attr.use_assoc || sym->attr.intrinsic) + if (sym->attr.external || sym->attr.use_assoc || sym->attr.intrinsic + || sym->attr.if_source != IFSRC_DECL) { decl = gfc_get_extern_function_decl (sym); gfc_set_decl_location (decl, &sym->declared_at); diff -Naur gcc-4.8.2.orig/gcc/fortran/trans-expr.c gcc-4.8.2/gcc/fortran/trans-expr.c --- gcc-4.8.2.orig/gcc/fortran/trans-expr.c 2013-01-29 21:40:51.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/trans-expr.c 2014-03-30 20:21:40.670929339 +0000 @@ -355,7 +355,11 @@ gfc_conv_expr_descriptor (parmse, e); if (e->rank != class_ts.u.derived->components->as->rank) - class_array_data_assign (&block, ctree, parmse->expr, true); + { + gcc_assert (class_ts.u.derived->components->as->type + == AS_ASSUMED_RANK); + class_array_data_assign (&block, ctree, parmse->expr, false); + } else { if (gfc_expr_attr (e).codimension) @@ -670,7 +674,6 @@ gfc_add_modify (&parmse->post, vptr, fold_convert (TREE_TYPE (vptr), ctree)); - gcc_assert (!optional || (optional && !copyback)); if (optional) { tree tmp2; @@ -6343,7 +6346,13 @@ /* Returns a reference to the scalar evaluated outside the loop for this case. */ gfc_conv_expr (se, expr); - se->expr = gfc_build_addr_expr (NULL_TREE, se->expr); + + if (expr->ts.type == BT_CHARACTER + && expr->expr_type != EXPR_FUNCTION) + gfc_conv_string_parameter (se); + else + se->expr = gfc_build_addr_expr (NULL_TREE, se->expr); + return; } diff -Naur gcc-4.8.2.orig/gcc/fortran/trans-intrinsic.c gcc-4.8.2/gcc/fortran/trans-intrinsic.c --- gcc-4.8.2.orig/gcc/fortran/trans-intrinsic.c 2013-08-11 11:31:41.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/trans-intrinsic.c 2014-03-30 20:21:40.670929339 +0000 @@ -4684,9 +4684,11 @@ static void gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr) { - tree args[2], type, pchartype; + tree args[3], type, pchartype; + int nargs; - gfc_conv_intrinsic_function_args (se, expr, args, 2); + nargs = gfc_intrinsic_argument_list_length (expr); + gfc_conv_intrinsic_function_args (se, expr, args, nargs); gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1]))); pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind); args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]); diff -Naur gcc-4.8.2.orig/gcc/fortran/trans-io.c gcc-4.8.2/gcc/fortran/trans-io.c --- gcc-4.8.2.orig/gcc/fortran/trans-io.c 2013-03-01 10:24:11.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/trans-io.c 2014-03-30 20:21:40.670929339 +0000 @@ -243,16 +243,16 @@ /* The code to generate the error. */ gfc_start_block (&block); - + arg1 = gfc_build_addr_expr (NULL_TREE, var); - + arg2 = build_int_cst (integer_type_node, error_code), - + asprintf (&message, "%s", _(msgid)); arg3 = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const (message)); free (message); - + tmp = build_call_expr_loc (input_location, gfor_fndecl_generate_error, 3, arg1, arg2, arg3); @@ -521,7 +521,7 @@ gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT, "Unit number in I/O statement too small", &se.pre); - + /* UNIT numbers should be less than the max. */ val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4); cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, @@ -1000,7 +1000,7 @@ if (p->convert) mask |= set_string (&block, &post_block, var, IOPARM_open_convert, p->convert); - + if (p->newunit) mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit, p->newunit); @@ -1234,7 +1234,7 @@ { mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist, p->exist); - + if (p->unit && !p->iostat) { p->iostat = create_dummy_iostat (); @@ -1322,7 +1322,7 @@ if (p->pad) mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad, p->pad); - + if (p->convert) mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert, p->convert); @@ -1547,7 +1547,7 @@ tree dtype; tree dt_parm_addr; tree decl = NULL_TREE; - int n_dim; + int n_dim; int itype; int rank = 0; @@ -2032,7 +2032,7 @@ if (gfc_notification_std (GFC_STD_GNU) != SILENT) { gfc_error_now ("Derived type '%s' at %L has PRIVATE components", - ts->u.derived->name, code != NULL ? &(code->loc) : + ts->u.derived->name, code != NULL ? &(code->loc) : &gfc_current_locus); return; } @@ -2041,7 +2041,7 @@ ts->kind = ts->u.derived->ts.kind; ts->f90_type = ts->u.derived->ts.f90_type; } - + kind = ts->kind; function = NULL; arg2 = NULL; @@ -2123,7 +2123,7 @@ function = iocall[IOCALL_X_CHARACTER_WIDE]; else function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE]; - + tmp = gfc_build_addr_expr (NULL_TREE, dt_parm); tmp = build_call_expr_loc (input_location, function, 4, tmp, addr_expr, arg2, arg3); @@ -2158,6 +2158,12 @@ expr = build_fold_indirect_ref_loc (input_location, expr); + /* Make sure that the derived type has been built. An external + function, if only referenced in an io statement requires this + check (see PR58771). */ + if (ts->u.derived->backend_decl == NULL_TREE) + tmp = gfc_typenode_for_spec (ts); + for (c = ts->u.derived->components; c; c = c->next) { field = c->backend_decl; diff -Naur gcc-4.8.2.orig/gcc/fortran/trans-stmt.c gcc-4.8.2/gcc/fortran/trans-stmt.c --- gcc-4.8.2.orig/gcc/fortran/trans-stmt.c 2013-01-29 21:40:51.000000000 +0000 +++ gcc-4.8.2/gcc/fortran/trans-stmt.c 2014-03-30 20:21:40.674262780 +0000 @@ -5104,10 +5104,49 @@ { gfc_expr *lhs, *rhs; gfc_se lse; + gfc_ref *ref, *class_ref, *tail; + + /* Find the last class reference. */ + class_ref = NULL; + for (ref = e->ref; ref; ref = ref->next) + { + if (ref->type == REF_COMPONENT + && ref->u.c.component->ts.type == BT_CLASS) + class_ref = ref; + + if (ref->next == NULL) + break; + } + + /* Remove and store all subsequent references after the + CLASS reference. */ + if (class_ref) + { + tail = class_ref->next; + class_ref->next = NULL; + } + else + { + tail = e->ref; + e->ref = NULL; + } lhs = gfc_expr_to_initialize (e); gfc_add_vptr_component (lhs); + /* Remove the _vptr component and restore the original tail + references. */ + if (class_ref) + { + gfc_free_ref_list (class_ref->next); + class_ref->next = tail; + } + else + { + gfc_free_ref_list (e->ref); + e->ref = tail; + } + if (class_expr != NULL_TREE) { /* Polymorphic SOURCE: VPTR must be determined at run time. */ diff -Naur gcc-4.8.2.orig/gcc/gcc.c gcc-4.8.2/gcc/gcc.c --- gcc-4.8.2.orig/gcc/gcc.c 2013-05-17 12:24:26.000000000 +0000 +++ gcc-4.8.2/gcc/gcc.c 2014-03-30 20:21:40.674262780 +0000 @@ -5441,7 +5441,7 @@ const char *save_suffix_subst; int save_growing_size; - void *save_growing_value; + void *save_growing_value = NULL; sf = lookup_spec_function (func); if (sf == NULL) diff -Naur gcc-4.8.2.orig/gcc/gimple-fold.c gcc-4.8.2/gcc/gimple-fold.c --- gcc-4.8.2.orig/gcc/gimple-fold.c 2013-01-13 12:33:43.000000000 +0000 +++ gcc-4.8.2/gcc/gimple-fold.c 2014-03-30 20:21:40.677596222 +0000 @@ -178,7 +178,7 @@ /* Make sure we create a cgraph node for functions we'll reference. They can be non-existent if the reference comes from an entry of an external vtable for example. */ - cgraph_get_create_node (base); + cgraph_get_create_real_symbol_node (base); } /* Fixup types in global initializers. */ if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0))) @@ -866,6 +866,7 @@ break; case BUILT_IN_STRCPY: case BUILT_IN_STRNCPY: + case BUILT_IN_STRCAT: arg_idx = 1; type = 0; break; @@ -941,6 +942,13 @@ val[1]); break; + case BUILT_IN_STRCAT: + if (val[1] && is_gimple_val (val[1]) && nargs == 2) + result = fold_builtin_strcat (loc, gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 1), + val[1]); + break; + case BUILT_IN_FPUTS: if (nargs == 2) result = fold_builtin_fputs (loc, gimple_call_arg (stmt, 0), diff -Naur gcc-4.8.2.orig/gcc/gimple-low.c gcc-4.8.2/gcc/gimple-low.c --- gcc-4.8.2.orig/gcc/gimple-low.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/gimple-low.c 2014-03-30 20:21:40.677596222 +0000 @@ -238,6 +238,7 @@ break; arg = gimple_call_arg (stmt, i); if (p == error_mark_node + || DECL_ARG_TYPE (p) == error_mark_node || arg == error_mark_node || (!types_compatible_p (DECL_ARG_TYPE (p), TREE_TYPE (arg)) && !fold_convertible_p (DECL_ARG_TYPE (p), arg))) diff -Naur gcc-4.8.2.orig/gcc/gimple.c gcc-4.8.2/gcc/gimple.c --- gcc-4.8.2.orig/gcc/gimple.c 2013-08-16 09:06:41.000000000 +0000 +++ gcc-4.8.2/gcc/gimple.c 2014-03-30 20:21:40.674262780 +0000 @@ -3841,42 +3841,46 @@ /* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and VISIT_ADDR if non-NULL on loads, store and address-taken operands - passing the STMT, the base of the operand and DATA to it. The base - will be either a decl, an indirect reference (including TARGET_MEM_REF) - or the argument of an address expression. + passing the STMT, the base of the operand, the operand itself containing + the base and DATA to it. The base will be either a decl, an indirect + reference (including TARGET_MEM_REF) or the argument of an address + expression. Returns the results of these callbacks or'ed. */ bool walk_stmt_load_store_addr_ops (gimple stmt, void *data, - bool (*visit_load)(gimple, tree, void *), - bool (*visit_store)(gimple, tree, void *), - bool (*visit_addr)(gimple, tree, void *)) + walk_stmt_load_store_addr_fn visit_load, + walk_stmt_load_store_addr_fn visit_store, + walk_stmt_load_store_addr_fn visit_addr) { bool ret = false; unsigned i; if (gimple_assign_single_p (stmt)) { - tree lhs, rhs; + tree lhs, rhs, arg; if (visit_store) { - lhs = get_base_loadstore (gimple_assign_lhs (stmt)); + arg = gimple_assign_lhs (stmt); + lhs = get_base_loadstore (arg); if (lhs) - ret |= visit_store (stmt, lhs, data); + ret |= visit_store (stmt, lhs, arg, data); } - rhs = gimple_assign_rhs1 (stmt); + arg = gimple_assign_rhs1 (stmt); + rhs = arg; while (handled_component_p (rhs)) rhs = TREE_OPERAND (rhs, 0); if (visit_addr) { if (TREE_CODE (rhs) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data); else if (TREE_CODE (rhs) == TARGET_MEM_REF && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), arg, + data); else if (TREE_CODE (rhs) == OBJ_TYPE_REF && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs), - 0), data); + 0), arg, data); else if (TREE_CODE (rhs) == CONSTRUCTOR) { unsigned int ix; @@ -3884,23 +3888,23 @@ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val) if (TREE_CODE (val) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data); else if (TREE_CODE (val) == OBJ_TYPE_REF && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val), - 0), data); + 0), arg, data); } lhs = gimple_assign_lhs (stmt); if (TREE_CODE (lhs) == TARGET_MEM_REF && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), lhs, data); } if (visit_load) { rhs = get_base_loadstore (rhs); if (rhs) - ret |= visit_load (stmt, rhs, data); + ret |= visit_load (stmt, rhs, arg, data); } } else if (visit_addr @@ -3913,17 +3917,17 @@ if (op == NULL_TREE) ; else if (TREE_CODE (op) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data); /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison tree with two operands. */ else if (i == 1 && COMPARISON_CLASS_P (op)) { if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0), - 0), data); + 0), op, data); if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1), - 0), data); + 0), op, data); } } } @@ -3931,38 +3935,39 @@ { if (visit_store) { - tree lhs = gimple_call_lhs (stmt); - if (lhs) + tree arg = gimple_call_lhs (stmt); + if (arg) { - lhs = get_base_loadstore (lhs); + tree lhs = get_base_loadstore (arg); if (lhs) - ret |= visit_store (stmt, lhs, data); + ret |= visit_store (stmt, lhs, arg, data); } } if (visit_load || visit_addr) for (i = 0; i < gimple_call_num_args (stmt); ++i) { - tree rhs = gimple_call_arg (stmt, i); + tree arg = gimple_call_arg (stmt, i); if (visit_addr - && TREE_CODE (rhs) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data); + && TREE_CODE (arg) == ADDR_EXPR) + ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data); else if (visit_load) { - rhs = get_base_loadstore (rhs); + tree rhs = get_base_loadstore (arg); if (rhs) - ret |= visit_load (stmt, rhs, data); + ret |= visit_load (stmt, rhs, arg, data); } } if (visit_addr && gimple_call_chain (stmt) && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0), - data); + gimple_call_chain (stmt), data); if (visit_addr && gimple_call_return_slot_opt_p (stmt) && gimple_call_lhs (stmt) != NULL_TREE && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt)))) - ret |= visit_addr (stmt, gimple_call_lhs (stmt), data); + ret |= visit_addr (stmt, gimple_call_lhs (stmt), + gimple_call_lhs (stmt), data); } else if (gimple_code (stmt) == GIMPLE_ASM) { @@ -3978,7 +3983,7 @@ tree link = gimple_asm_output_op (stmt, i); tree op = get_base_loadstore (TREE_VALUE (link)); if (op && visit_store) - ret |= visit_store (stmt, op, data); + ret |= visit_store (stmt, op, TREE_VALUE (link), data); if (visit_addr) { constraint = TREE_STRING_POINTER @@ -3987,7 +3992,7 @@ parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg, &is_inout); if (op && !allows_reg && allows_mem) - ret |= visit_addr (stmt, op, data); + ret |= visit_addr (stmt, op, TREE_VALUE (link), data); } } if (visit_load || visit_addr) @@ -3997,14 +4002,14 @@ tree op = TREE_VALUE (link); if (visit_addr && TREE_CODE (op) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data); else if (visit_load || visit_addr) { op = get_base_loadstore (op); if (op) { if (visit_load) - ret |= visit_load (stmt, op, data); + ret |= visit_load (stmt, op, TREE_VALUE (link), data); if (visit_addr) { constraint = TREE_STRING_POINTER @@ -4013,7 +4018,8 @@ 0, oconstraints, &allows_mem, &allows_reg); if (!allows_reg && allows_mem) - ret |= visit_addr (stmt, op, data); + ret |= visit_addr (stmt, op, TREE_VALUE (link), + data); } } } @@ -4026,12 +4032,12 @@ { if (visit_addr && TREE_CODE (op) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data); else if (visit_load) { - op = get_base_loadstore (op); - if (op) - ret |= visit_load (stmt, op, data); + tree base = get_base_loadstore (op); + if (base) + ret |= visit_load (stmt, base, op, data); } } } @@ -4042,7 +4048,7 @@ { tree op = PHI_ARG_DEF (stmt, i); if (TREE_CODE (op) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data); } } else if (visit_addr @@ -4050,7 +4056,7 @@ { tree op = gimple_goto_dest (stmt); if (TREE_CODE (op) == ADDR_EXPR) - ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data); + ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data); } return ret; @@ -4061,8 +4067,8 @@ bool walk_stmt_load_store_ops (gimple stmt, void *data, - bool (*visit_load)(gimple, tree, void *), - bool (*visit_store)(gimple, tree, void *)) + walk_stmt_load_store_addr_fn visit_load, + walk_stmt_load_store_addr_fn visit_store) { return walk_stmt_load_store_addr_ops (stmt, data, visit_load, visit_store, NULL); @@ -4071,8 +4077,7 @@ /* Helper for gimple_ior_addresses_taken_1. */ static bool -gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED, - tree addr, void *data) +gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data) { bitmap addresses_taken = (bitmap)data; addr = get_base_address (addr); diff -Naur gcc-4.8.2.orig/gcc/gimple.h gcc-4.8.2/gcc/gimple.h --- gcc-4.8.2.orig/gcc/gimple.h 2013-03-08 22:26:37.000000000 +0000 +++ gcc-4.8.2/gcc/gimple.h 2014-03-30 20:21:40.677596222 +0000 @@ -888,13 +888,14 @@ extern alias_set_type gimple_get_alias_set (tree); extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *, unsigned *); +typedef bool (*walk_stmt_load_store_addr_fn) (gimple, tree, tree, void *); extern bool walk_stmt_load_store_addr_ops (gimple, void *, - bool (*)(gimple, tree, void *), - bool (*)(gimple, tree, void *), - bool (*)(gimple, tree, void *)); + walk_stmt_load_store_addr_fn, + walk_stmt_load_store_addr_fn, + walk_stmt_load_store_addr_fn); extern bool walk_stmt_load_store_ops (gimple, void *, - bool (*)(gimple, tree, void *), - bool (*)(gimple, tree, void *)); + walk_stmt_load_store_addr_fn, + walk_stmt_load_store_addr_fn); extern bool gimple_ior_addresses_taken (bitmap, gimple); extern bool gimple_call_builtin_p (gimple, enum built_in_class); extern bool gimple_call_builtin_p (gimple, enum built_in_function); diff -Naur gcc-4.8.2.orig/gcc/gimplify.c gcc-4.8.2/gcc/gimplify.c --- gcc-4.8.2.orig/gcc/gimplify.c 2013-01-28 14:05:40.000000000 +0000 +++ gcc-4.8.2/gcc/gimplify.c 2014-03-30 20:21:40.677596222 +0000 @@ -2060,6 +2060,9 @@ /* Nonlocal VLAs seen in the current function. */ static struct pointer_set_t *nonlocal_vlas; +/* The VAR_DECLs created for nonlocal VLAs for debug info purposes. */ +static tree nonlocal_vla_vars; + /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a DECL_VALUE_EXPR, and it's worth re-examining things. */ @@ -2106,14 +2109,13 @@ ctx = ctx->outer_context; if (!ctx && !pointer_set_insert (nonlocal_vlas, decl)) { - tree copy = copy_node (decl), block; + tree copy = copy_node (decl); lang_hooks.dup_lang_specific_decl (copy); SET_DECL_RTL (copy, 0); TREE_USED (copy) = 1; - block = DECL_INITIAL (current_function_decl); - DECL_CHAIN (copy) = BLOCK_VARS (block); - BLOCK_VARS (block) = copy; + DECL_CHAIN (copy) = nonlocal_vla_vars; + nonlocal_vla_vars = copy; SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr)); DECL_HAS_VALUE_EXPR_P (copy) = 1; } @@ -4369,7 +4371,7 @@ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); if (offset / part_widthi - <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) + < TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0), part_width, index); } @@ -6131,7 +6133,7 @@ region's REDUCTION clause. */ static bool -omp_check_private (struct gimplify_omp_ctx *ctx, tree decl) +omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate) { splay_tree_node n; @@ -6140,8 +6142,11 @@ ctx = ctx->outer_context; if (ctx == NULL) return !(is_global_var (decl) - /* References might be private, but might be shared too. */ - || lang_hooks.decls.omp_privatize_by_reference (decl)); + /* References might be private, but might be shared too, + when checking for copyprivate, assume they might be + private, otherwise assume they might be shared. */ + || (!copyprivate + && lang_hooks.decls.omp_privatize_by_reference (decl))); n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); if (n != NULL) @@ -6267,12 +6272,36 @@ remove = true; break; } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE + && !remove + && !omp_check_private (ctx, decl, true)) + { + remove = true; + if (is_global_var (decl)) + { + if (DECL_THREAD_LOCAL_P (decl)) + remove = false; + else if (DECL_HAS_VALUE_EXPR_P (decl)) + { + tree value = get_base_address (DECL_VALUE_EXPR (decl)); + + if (value + && DECL_P (value) + && DECL_THREAD_LOCAL_P (value)) + remove = false; + } + } + if (remove) + error_at (OMP_CLAUSE_LOCATION (c), + "copyprivate variable %qE is not threadprivate" + " or private in outer context", DECL_NAME (decl)); + } do_notice: if (outer_ctx) omp_notice_variable (outer_ctx, decl, true); if (check_non_private && region_type == ORT_WORKSHARE - && omp_check_private (ctx, decl)) + && omp_check_private (ctx, decl, false)) { error ("%s variable %qE is private in outer context", check_non_private, DECL_NAME (decl)); @@ -8261,6 +8290,21 @@ if (nonlocal_vlas) { + if (nonlocal_vla_vars) + { + /* tree-nested.c may later on call declare_vars (..., true); + which relies on BLOCK_VARS chain to be the tail of the + gimple_bind_vars chain. Ensure we don't violate that + assumption. */ + if (gimple_bind_block (outer_bind) + == DECL_INITIAL (current_function_decl)) + declare_vars (nonlocal_vla_vars, outer_bind, true); + else + BLOCK_VARS (DECL_INITIAL (current_function_decl)) + = chainon (BLOCK_VARS (DECL_INITIAL (current_function_decl)), + nonlocal_vla_vars); + nonlocal_vla_vars = NULL_TREE; + } pointer_set_destroy (nonlocal_vlas); nonlocal_vlas = NULL; } diff -Naur gcc-4.8.2.orig/gcc/go/go-gcc.cc gcc-4.8.2/gcc/go/go-gcc.cc --- gcc-4.8.2.orig/gcc/go/go-gcc.cc 2013-10-04 18:07:35.000000000 +0000 +++ gcc-4.8.2/gcc/go/go-gcc.cc 2014-03-30 20:21:40.687596554 +0000 @@ -232,6 +232,9 @@ Bexpression* convert_expression(Btype* type, Bexpression* expr, Location); + Bexpression* + function_code_expression(Bfunction*, Location); + // Statements. Bstatement* @@ -334,6 +337,17 @@ Bexpression* label_address(Blabel*, Location); + // Functions. + + Bfunction* + error_function() + { return this->make_function(error_mark_node); } + + Bfunction* + function(Btype* fntype, const std::string& name, const std::string& asm_name, + bool is_visible, bool is_declaration, bool is_inlinable, + bool disable_split_stack, bool in_unique_section, Location); + private: // Make a Bexpression from a tree. Bexpression* @@ -350,6 +364,10 @@ make_type(tree t) { return new Btype(t); } + Bfunction* + make_function(tree t) + { return new Bfunction(t); } + Btype* fill_in_struct(Btype*, const std::vector&); @@ -966,6 +984,19 @@ return tree_to_expr(ret); } +// Get the address of a function. + +Bexpression* +Gcc_backend::function_code_expression(Bfunction* bfunc, Location location) +{ + tree func = bfunc->get_tree(); + if (func == error_mark_node) + return this->error_expression(); + + tree ret = build_fold_addr_expr_loc(location.gcc_location(), func); + return this->make_expression(ret); +} + // An expression as a statement. Bstatement* @@ -1724,6 +1755,56 @@ return this->make_expression(ret); } +// Declare or define a new function. + +Bfunction* +Gcc_backend::function(Btype* fntype, const std::string& name, + const std::string& asm_name, bool is_visible, + bool is_declaration, bool is_inlinable, + bool disable_split_stack, bool in_unique_section, + Location location) +{ + tree functype = fntype->get_tree(); + if (functype != error_mark_node) + { + gcc_assert(FUNCTION_POINTER_TYPE_P(functype)); + functype = TREE_TYPE(functype); + } + tree id = get_identifier_from_string(name); + if (functype == error_mark_node || id == error_mark_node) + return this->error_function(); + + tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype); + if (!asm_name.empty()) + SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + if (is_visible) + TREE_PUBLIC(decl) = 1; + if (is_declaration) + DECL_EXTERNAL(decl) = 1; + else + { + tree restype = TREE_TYPE(functype); + tree resdecl = + build_decl(location.gcc_location(), RESULT_DECL, NULL_TREE, restype); + DECL_ARTIFICIAL(resdecl) = 1; + DECL_IGNORED_P(resdecl) = 1; + DECL_CONTEXT(resdecl) = decl; + DECL_RESULT(decl) = resdecl; + } + if (!is_inlinable) + DECL_UNINLINABLE(decl) = 1; + if (disable_split_stack) + { + tree attr = get_identifier("__no_split_stack__"); + DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE); + } + if (in_unique_section) + resolve_unique_section(decl, 0, 1); + + go_preserve_from_gc(decl); + return new Bfunction(decl); +} + // The single backend. static Gcc_backend gcc_backend; @@ -1799,3 +1880,9 @@ { return bv->get_tree(); } + +tree +function_to_tree(Bfunction* bf) +{ + return bf->get_tree(); +} diff -Naur gcc-4.8.2.orig/gcc/go/go-lang.c gcc-4.8.2/gcc/go/go-lang.c --- gcc-4.8.2.orig/gcc/go/go-lang.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/go/go-lang.c 2014-03-30 20:21:40.687596554 +0000 @@ -269,6 +269,10 @@ if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT) flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD; + /* Tail call optimizations can confuse uses of runtime.Callers. */ + if (!global_options_set.x_flag_optimize_sibling_calls) + global_options.x_flag_optimize_sibling_calls = 0; + /* Returning false means that the backend should be used. */ return false; } diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/backend.h gcc-4.8.2/gcc/go/gofrontend/backend.h --- gcc-4.8.2.orig/gcc/go/gofrontend/backend.h 2013-10-04 18:07:35.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/backend.h 2014-03-30 20:21:40.680929667 +0000 @@ -23,7 +23,7 @@ // The backend representation of a statement. class Bstatement; -// The backend representation of a function definition. +// The backend representation of a function definition or declaration. class Bfunction; // The backend representation of a block. @@ -266,6 +266,11 @@ virtual Bexpression* convert_expression(Btype* type, Bexpression* expr, Location) = 0; + // Create an expression for the address of a function. This is used to + // get the address of the code for a function. + virtual Bexpression* + function_code_expression(Bfunction*, Location) = 0; + // Statements. // Create an error statement. This is used for cases which should @@ -498,6 +503,32 @@ // recover. virtual Bexpression* label_address(Blabel*, Location) = 0; + + // Functions. + + // Create an error function. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // going without crashing. + virtual Bfunction* + error_function() = 0; + + // Declare or define a function of FNTYPE. + // NAME is the Go name of the function. ASM_NAME, if not the empty string, is + // the name that should be used in the symbol table; this will be non-empty if + // a magic extern comment is used. + // IS_VISIBLE is true if this function should be visible outside of the + // current compilation unit. IS_DECLARATION is true if this is a function + // declaration rather than a definition; the function definition will be in + // another compilation unit. + // IS_INLINABLE is true if the function can be inlined. + // DISABLE_SPLIT_STACK is true if this function may not split the stack; this + // is used for the implementation of recover. + // IN_UNIQUE_SECTION is true if this function should be put into a unique + // location if possible; this is used for field tracking. + virtual Bfunction* + function(Btype* fntype, const std::string& name, const std::string& asm_name, + bool is_visible, bool is_declaration, bool is_inlinable, + bool disable_split_stack, bool in_unique_section, Location) = 0; }; // The backend interface has to define this function. @@ -517,5 +548,6 @@ extern tree stat_to_tree(Bstatement*); extern tree block_to_tree(Bblock*); extern tree var_to_tree(Bvariable*); +extern tree function_to_tree(Bfunction*); #endif // !defined(GO_BACKEND_H) diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/expressions.cc gcc-4.8.2/gcc/go/gofrontend/expressions.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/expressions.cc 2013-10-08 23:54:31.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/expressions.cc 2014-03-30 20:21:40.680929667 +0000 @@ -1219,7 +1219,7 @@ // Get the tree for the code of a function expression. -tree +Bexpression* Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc) { Function_type* fntype; @@ -1237,25 +1237,18 @@ error_at(loc, "invalid use of special builtin function %qs; must be called", no->message_name().c_str()); - return error_mark_node; + return gogo->backend()->error_expression(); } - tree id = no->get_id(gogo); - if (id == error_mark_node) - return error_mark_node; - - tree fndecl; + Bfunction* fndecl; if (no->is_function()) - fndecl = no->func_value()->get_or_make_decl(gogo, no, id); + fndecl = no->func_value()->get_or_make_decl(gogo, no); else if (no->is_function_declaration()) - fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no, id); + fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no); else go_unreachable(); - if (fndecl == error_mark_node) - return error_mark_node; - - return build_fold_addr_expr_loc(loc.gcc_location(), fndecl); + return gogo->backend()->function_code_expression(fndecl, loc); } // Get the tree for a function expression. This is used when we take @@ -1492,8 +1485,10 @@ tree Func_code_reference_expression::do_get_tree(Translate_context* context) { - return Func_expression::get_code_pointer(context->gogo(), this->function_, - this->location()); + Bexpression* ret = + Func_expression::get_code_pointer(context->gogo(), this->function_, + this->location()); + return expr_to_tree(ret); } // Make a reference to the code of a function. @@ -3055,8 +3050,7 @@ do_lower(Gogo*, Named_object*, Statement_inserter*, int); bool - do_is_constant() const - { return this->expr_->is_constant(); } + do_is_constant() const; bool do_numeric_constant_value(Numeric_constant*) const; @@ -3198,6 +3192,27 @@ return this; } +// Return whether a type conversion is a constant. + +bool +Type_conversion_expression::do_is_constant() const +{ + if (!this->expr_->is_constant()) + return false; + + // A conversion to a type that may not be used as a constant is not + // a constant. For example, []byte(nil). + Type* type = this->type_; + if (type->integer_type() == NULL + && type->float_type() == NULL + && type->complex_type() == NULL + && !type->is_boolean_type() + && !type->is_string_type()) + return false; + + return true; +} + // Return the constant numeric value if there is one. bool @@ -5586,6 +5601,15 @@ subcontext.type = NULL; } + if (this->op_ == OPERATOR_ANDAND || this->op_ == OPERATOR_OROR) + { + // For a logical operation, the context does not determine the + // types of the operands. The operands must be some boolean + // type but if the context has a boolean type they do not + // inherit it. See http://golang.org/issue/3924. + subcontext.type = NULL; + } + // Set the context for the left hand operand. if (is_shift_op) { @@ -5967,6 +5991,43 @@ right); } + // For complex division Go wants slightly different results than the + // GCC library provides, so we have our own runtime routine. + if (this->op_ == OPERATOR_DIV && this->left_->type()->complex_type() != NULL) + { + const char *name; + tree *pdecl; + Type* ctype; + static tree complex64_div_decl; + static tree complex128_div_decl; + switch (this->left_->type()->complex_type()->bits()) + { + case 64: + name = "__go_complex64_div"; + pdecl = &complex64_div_decl; + ctype = Type::lookup_complex_type("complex64"); + break; + case 128: + name = "__go_complex128_div"; + pdecl = &complex128_div_decl; + ctype = Type::lookup_complex_type("complex128"); + break; + default: + go_unreachable(); + } + Btype* cbtype = ctype->get_backend(gogo); + tree ctype_tree = type_to_tree(cbtype); + return Gogo::call_builtin(pdecl, + this->location(), + name, + 2, + ctype_tree, + ctype_tree, + fold_convert_loc(gccloc, ctype_tree, left), + type, + fold_convert_loc(gccloc, ctype_tree, right)); + } + tree compute_type = excess_precision_type(type); if (compute_type != NULL_TREE) { @@ -7191,6 +7252,15 @@ if (this->code_ == BUILTIN_OFFSETOF) { Expression* arg = this->one_arg(); + + if (arg->bound_method_expression() != NULL + || arg->interface_field_reference_expression() != NULL) + { + this->report_error(_("invalid use of method value as argument " + "of Offsetof")); + return this; + } + Field_reference_expression* farg = arg->field_reference_expression(); while (farg != NULL) { @@ -7200,7 +7270,8 @@ // it must not be reached through pointer indirections. if (farg->expr()->deref() != farg->expr()) { - this->report_error(_("argument of Offsetof implies indirection of an embedded field")); + this->report_error(_("argument of Offsetof implies " + "indirection of an embedded field")); return this; } // Go up until we reach the original base. @@ -7476,7 +7547,7 @@ switch (nc.to_unsigned_long(&v)) { case Numeric_constant::NC_UL_VALID: - return true; + break; case Numeric_constant::NC_UL_NOTINT: error_at(e->location(), "non-integer %s argument to make", is_length ? "len" : "cap"); @@ -7488,8 +7559,23 @@ case Numeric_constant::NC_UL_BIG: // We don't want to give a compile-time error for a 64-bit // value on a 32-bit target. - return true; + break; } + + mpz_t val; + if (!nc.to_int(&val)) + go_unreachable(); + int bits = mpz_sizeinbase(val, 2); + mpz_clear(val); + Type* int_type = Type::lookup_integer_type("int"); + if (bits >= int_type->integer_type()->bits()) + { + error_at(e->location(), "%s argument too large for make", + is_length ? "len" : "cap"); + return false; + } + + return true; } if (e->type()->integer_type() != NULL) @@ -7595,6 +7681,8 @@ bool Builtin_call_expression::do_is_constant() const { + if (this->is_error_expression()) + return true; switch (this->code_) { case BUILTIN_LEN: @@ -9744,14 +9832,8 @@ } tree fntype_tree = type_to_tree(fntype->get_backend(gogo)); - if (fntype_tree == error_mark_node) - return error_mark_node; - go_assert(POINTER_TYPE_P(fntype_tree)); - if (TREE_TYPE(fntype_tree) == error_mark_node) - return error_mark_node; - go_assert(TREE_CODE(TREE_TYPE(fntype_tree)) == RECORD_TYPE); - tree fnfield_type = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(fntype_tree))); - if (fnfield_type == error_mark_node) + tree fnfield_type = type_to_tree(fntype->get_backend_fntype(gogo)); + if (fntype_tree == error_mark_node || fnfield_type == error_mark_node) return error_mark_node; go_assert(FUNCTION_POINTER_TYPE_P(fnfield_type)); tree rettype = TREE_TYPE(TREE_TYPE(fnfield_type)); @@ -9763,7 +9845,7 @@ if (func != NULL) { Named_object* no = func->named_object(); - fn = Func_expression::get_code_pointer(gogo, no, location); + fn = expr_to_tree(Func_expression::get_code_pointer(gogo, no, location)); if (!has_closure) closure_tree = NULL_TREE; else @@ -10817,11 +10899,20 @@ void String_index_expression::do_check_types(Gogo*) { - if (this->start_->type()->integer_type() == NULL) + Numeric_constant nc; + unsigned long v; + if (this->start_->type()->integer_type() == NULL + && !this->start_->type()->is_error() + && (!this->start_->numeric_constant_value(&nc) + || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT)) this->report_error(_("index must be integer")); if (this->end_ != NULL && this->end_->type()->integer_type() == NULL - && !this->end_->is_nil_expression()) + && !this->end_->type()->is_error() + && !this->end_->is_nil_expression() + && !this->end_->is_error_expression() + && (!this->end_->numeric_constant_value(&nc) + || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT)) this->report_error(_("slice end must be integer")); std::string sval; diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/expressions.h gcc-4.8.2/gcc/go/gofrontend/expressions.h --- gcc-4.8.2.orig/gcc/go/gofrontend/expressions.h 2013-10-08 23:54:31.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/expressions.h 2014-03-30 20:21:40.680929667 +0000 @@ -1514,8 +1514,8 @@ closure() { return this->closure_; } - // Return a tree for the code for a function. - static tree + // Return a backend expression for the code of a function. + static Bexpression* get_code_pointer(Gogo*, Named_object* function, Location loc); protected: diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/gogo-tree.cc gcc-4.8.2/gcc/go/gofrontend/gogo-tree.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/gogo-tree.cc 2013-09-28 20:23:56.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/gogo-tree.cc 2014-03-30 20:21:40.684263111 +0000 @@ -985,74 +985,6 @@ delete[] vec; } -// Get a tree for the identifier for a named object. - -tree -Named_object::get_id(Gogo* gogo) -{ - go_assert(!this->is_variable() && !this->is_result_variable()); - std::string decl_name; - if (this->is_function_declaration() - && !this->func_declaration_value()->asm_name().empty()) - decl_name = this->func_declaration_value()->asm_name(); - else if (this->is_type() - && Linemap::is_predeclared_location(this->type_value()->location())) - { - // We don't need the package name for builtin types. - decl_name = Gogo::unpack_hidden_name(this->name_); - } - else - { - std::string package_name; - if (this->package_ == NULL) - package_name = gogo->package_name(); - else - package_name = this->package_->package_name(); - - // Note that this will be misleading if this is an unexported - // method generated for an embedded imported type. In that case - // the unexported method should have the package name of the - // package from which it is imported, but we are going to give - // it our package name. Fixing this would require knowing the - // package name, but we only know the package path. It might be - // better to use package paths here anyhow. This doesn't affect - // the assembler code, because we always set that name in - // Function::get_or_make_decl anyhow. FIXME. - - decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_); - - Function_type* fntype; - if (this->is_function()) - fntype = this->func_value()->type(); - else if (this->is_function_declaration()) - fntype = this->func_declaration_value()->type(); - else - fntype = NULL; - if (fntype != NULL && fntype->is_method()) - { - decl_name.push_back('.'); - decl_name.append(fntype->receiver()->type()->mangled_name(gogo)); - } - } - if (this->is_type()) - { - unsigned int index; - const Named_object* in_function = this->type_value()->in_function(&index); - if (in_function != NULL) - { - decl_name += '$' + Gogo::unpack_hidden_name(in_function->name()); - if (index > 0) - { - char buf[30]; - snprintf(buf, sizeof buf, "%u", index); - decl_name += '$'; - decl_name += buf; - } - } - } - return get_identifier_from_string(decl_name); -} - // Get a tree for a named object. tree @@ -1067,11 +999,6 @@ return error_mark_node; } - tree name; - if (this->classification_ == NAMED_OBJECT_TYPE) - name = NULL_TREE; - else - name = this->get_id(gogo); tree decl; switch (this->classification_) { @@ -1099,6 +1026,7 @@ decl = error_mark_node; else if (INTEGRAL_TYPE_P(TREE_TYPE(expr_tree))) { + tree name = get_identifier_from_string(this->get_id(gogo)); decl = build_decl(named_constant->location().gcc_location(), CONST_DECL, name, TREE_TYPE(expr_tree)); DECL_INITIAL(decl) = expr_tree; @@ -1161,7 +1089,7 @@ case NAMED_OBJECT_FUNC: { Function* func = this->u_.func_value; - decl = func->get_or_make_decl(gogo, this, name); + decl = function_to_tree(func->get_or_make_decl(gogo, this)); if (decl != error_mark_node) { if (func->block() != NULL) @@ -1286,123 +1214,12 @@ return block_tree; } -// Get a tree for a function decl. +// Get the backend representation. -tree -Function::get_or_make_decl(Gogo* gogo, Named_object* no, tree id) +Bfunction* +Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) { - if (this->fndecl_ == NULL_TREE) - { - tree functype = type_to_tree(this->type_->get_backend(gogo)); - - if (functype != error_mark_node) - { - // The type of a function comes back as a pointer to a - // struct whose first field is the function, but we want the - // real function type for a function declaration. - go_assert(POINTER_TYPE_P(functype) - && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE); - functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype))); - go_assert(FUNCTION_POINTER_TYPE_P(functype)); - functype = TREE_TYPE(functype); - } - - if (functype == error_mark_node) - this->fndecl_ = error_mark_node; - else - { - tree decl = build_decl(this->location().gcc_location(), FUNCTION_DECL, - id, functype); - - this->fndecl_ = decl; - - if (no->package() != NULL) - ; - else if (this->enclosing_ != NULL || Gogo::is_thunk(no)) - ; - else if (Gogo::unpack_hidden_name(no->name()) == "init" - && !this->type_->is_method()) - ; - else if (Gogo::unpack_hidden_name(no->name()) == "main" - && gogo->is_main_package()) - TREE_PUBLIC(decl) = 1; - // Methods have to be public even if they are hidden because - // they can be pulled into type descriptors when using - // anonymous fields. - else if (!Gogo::is_hidden_name(no->name()) - || this->type_->is_method()) - { - TREE_PUBLIC(decl) = 1; - std::string pkgpath = gogo->pkgpath_symbol(); - if (this->type_->is_method() - && Gogo::is_hidden_name(no->name()) - && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath()) - { - // This is a method we created for an unexported - // method of an imported embedded type. We need to - // use the pkgpath of the imported package to avoid - // a possible name collision. See bug478 for a test - // case. - pkgpath = Gogo::hidden_name_pkgpath(no->name()); - pkgpath = Gogo::pkgpath_for_symbol(pkgpath); - } - - std::string asm_name = pkgpath; - asm_name.append(1, '.'); - asm_name.append(Gogo::unpack_hidden_name(no->name())); - if (this->type_->is_method()) - { - asm_name.append(1, '.'); - Type* rtype = this->type_->receiver()->type(); - asm_name.append(rtype->mangled_name(gogo)); - } - SET_DECL_ASSEMBLER_NAME(decl, - get_identifier_from_string(asm_name)); - } - - // Why do we have to do this in the frontend? - tree restype = TREE_TYPE(functype); - tree resdecl = - build_decl(this->location().gcc_location(), RESULT_DECL, NULL_TREE, - restype); - DECL_ARTIFICIAL(resdecl) = 1; - DECL_IGNORED_P(resdecl) = 1; - DECL_CONTEXT(resdecl) = decl; - DECL_RESULT(decl) = resdecl; - - // If a function calls the predeclared recover function, we - // can't inline it, because recover behaves differently in a - // function passed directly to defer. If this is a recover - // thunk that we built to test whether a function can be - // recovered, we can't inline it, because that will mess up - // our return address comparison. - if (this->calls_recover_ || this->is_recover_thunk_) - DECL_UNINLINABLE(decl) = 1; - - // If this is a thunk created to call a function which calls - // the predeclared recover function, we need to disable - // stack splitting for the thunk. - if (this->is_recover_thunk_) - { - tree attr = get_identifier("__no_split_stack__"); - DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE); - } - - if (this->in_unique_section_) - resolve_unique_section (decl, 0, 1); - - go_preserve_from_gc(decl); - } - } - return this->fndecl_; -} - -// Get a tree for a function declaration. - -tree -Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no, tree id) -{ - if (this->fndecl_ == NULL_TREE) + if (this->fndecl_ == NULL) { // Let Go code use an asm declaration to pick up a builtin // function. @@ -1412,56 +1229,44 @@ builtin_functions.find(this->asm_name_); if (p != builtin_functions.end()) { - this->fndecl_ = p->second; + this->fndecl_ = tree_to_function(p->second); return this->fndecl_; } } - tree functype = type_to_tree(this->fntype_->get_backend(gogo)); + std::string asm_name; + if (this->asm_name_.empty()) + { + asm_name = (no->package() == NULL + ? gogo->pkgpath_symbol() + : no->package()->pkgpath_symbol()); + asm_name.append(1, '.'); + asm_name.append(Gogo::unpack_hidden_name(no->name())); + if (this->fntype_->is_method()) + { + asm_name.append(1, '.'); + Type* rtype = this->fntype_->receiver()->type(); + asm_name.append(rtype->mangled_name(gogo)); + } + } + + Btype* functype = this->fntype_->get_backend_fntype(gogo); + this->fndecl_ = + gogo->backend()->function(functype, no->get_id(gogo), asm_name, + true, true, true, false, false, + this->location()); + } - if (functype != error_mark_node) - { - // The type of a function comes back as a pointer to a - // struct whose first field is the function, but we want the - // real function type for a function declaration. - go_assert(POINTER_TYPE_P(functype) - && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE); - functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype))); - go_assert(FUNCTION_POINTER_TYPE_P(functype)); - functype = TREE_TYPE(functype); - } + return this->fndecl_; +} - tree decl; - if (functype == error_mark_node) - decl = error_mark_node; - else - { - decl = build_decl(this->location().gcc_location(), FUNCTION_DECL, id, - functype); - TREE_PUBLIC(decl) = 1; - DECL_EXTERNAL(decl) = 1; +// Return the function's decl after it has been built. - if (this->asm_name_.empty()) - { - std::string asm_name = (no->package() == NULL - ? gogo->pkgpath_symbol() - : no->package()->pkgpath_symbol()); - asm_name.append(1, '.'); - asm_name.append(Gogo::unpack_hidden_name(no->name())); - if (this->fntype_->is_method()) - { - asm_name.append(1, '.'); - Type* rtype = this->fntype_->receiver()->type(); - asm_name.append(rtype->mangled_name(gogo)); - } - SET_DECL_ASSEMBLER_NAME(decl, - get_identifier_from_string(asm_name)); - } - } - this->fndecl_ = decl; - go_preserve_from_gc(decl); - } - return this->fndecl_; +tree +Function::get_decl() const +{ + go_assert(this->fndecl_ != NULL); + return function_to_tree(this->fndecl_); } // We always pass the receiver to a method as a pointer. If the @@ -1558,7 +1363,7 @@ void Function::build_tree(Gogo* gogo, Named_object* named_function) { - tree fndecl = this->fndecl_; + tree fndecl = this->get_decl(); go_assert(fndecl != NULL_TREE); tree params = NULL_TREE; @@ -1796,7 +1601,7 @@ set = NULL_TREE; else set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node, - DECL_RESULT(this->fndecl_), retval); + DECL_RESULT(this->get_decl()), retval); tree ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR, void_type_node, set); append_to_statement_list(ret_stmt, &stmt_list); @@ -1851,7 +1656,7 @@ retval = this->return_value(gogo, named_function, end_loc, &stmt_list); set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node, - DECL_RESULT(this->fndecl_), retval); + DECL_RESULT(this->get_decl()), retval); ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR, void_type_node, set); @@ -1869,7 +1674,7 @@ *fini = stmt_list; } -// Return the value to assign to DECL_RESULT(this->fndecl_). This may +// Return the value to assign to DECL_RESULT(this->get_decl()). This may // also add statements to STMT_LIST, which need to be executed before // the assignment. This is used for a return statement with no // explicit values. @@ -1902,7 +1707,7 @@ } else { - tree rettype = TREE_TYPE(DECL_RESULT(this->fndecl_)); + tree rettype = TREE_TYPE(DECL_RESULT(this->get_decl())); retval = create_tmp_var(rettype, "RESULT"); tree field = TYPE_FIELDS(rettype); int index = 0; @@ -2323,18 +2128,14 @@ go_assert(m != NULL); Named_object* no = m->named_object(); - - tree fnid = no->get_id(this); - - tree fndecl; + Bfunction* bf; if (no->is_function()) - fndecl = no->func_value()->get_or_make_decl(this, no, fnid); + bf = no->func_value()->get_or_make_decl(this, no); else if (no->is_function_declaration()) - fndecl = no->func_declaration_value()->get_or_make_decl(this, no, - fnid); + bf = no->func_declaration_value()->get_or_make_decl(this, no); else go_unreachable(); - fndecl = build_fold_addr_expr(fndecl); + tree fndecl = build_fold_addr_expr(function_to_tree(bf)); elt = pointers->quick_push(empty); elt->index = size_int(i); @@ -2353,10 +2154,11 @@ TREE_CONSTANT(decl) = 1; DECL_INITIAL(decl) = constructor; - // If the interface type has hidden methods, then this is the only - // definition of the table. Otherwise it is a comdat table which - // may be defined in multiple packages. - if (has_hidden_methods) + // If the interface type has hidden methods, and the table is for a + // named type, then this is the only definition of the table. + // Otherwise it is a comdat table which may be defined in multiple + // packages. + if (has_hidden_methods && type->named_type() != NULL) TREE_PUBLIC(decl) = 1; else { diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/gogo.cc gcc-4.8.2/gcc/go/gofrontend/gogo.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/gogo.cc 2013-09-28 20:23:56.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/gogo.cc 2014-03-30 20:21:40.680929667 +0000 @@ -2822,7 +2822,10 @@ if (orig_fntype->is_varargs()) new_fntype->set_is_varargs(); - std::string name = orig_no->name() + "$recover"; + std::string name = orig_no->name(); + if (orig_fntype->is_method()) + name += "$" + orig_fntype->receiver()->type()->mangled_name(gogo); + name += "$recover"; Named_object *new_no = gogo->start_function(name, new_fntype, false, location); Function *new_func = new_no->func_value(); @@ -2916,7 +2919,25 @@ && !orig_rec_no->var_value()->is_receiver()); orig_rec_no->var_value()->set_is_receiver(); - const std::string& new_receiver_name(orig_fntype->receiver()->name()); + std::string new_receiver_name(orig_fntype->receiver()->name()); + if (new_receiver_name.empty()) + { + // Find the receiver. It was named "r.NNN" in + // Gogo::start_function. + for (Bindings::const_definitions_iterator p = + new_bindings->begin_definitions(); + p != new_bindings->end_definitions(); + ++p) + { + const std::string& pname((*p)->name()); + if (pname[0] == 'r' && pname[1] == '.') + { + new_receiver_name = pname; + break; + } + } + go_assert(!new_receiver_name.empty()); + } Named_object* new_rec_no = new_bindings->lookup_local(new_receiver_name); if (new_rec_no == NULL) go_assert(saw_errors()); @@ -3320,7 +3341,8 @@ closure_var_(NULL), block_(block), location_(location), labels_(), local_type_count_(0), descriptor_(NULL), fndecl_(NULL), defer_stack_(NULL), is_sink_(false), results_are_named_(false), nointerface_(false), - calls_recover_(false), is_recover_thunk_(false), has_recover_thunk_(false), + is_unnamed_type_stub_method_(false), calls_recover_(false), + is_recover_thunk_(false), has_recover_thunk_(false), in_unique_section_(false) { } @@ -3819,6 +3841,81 @@ *presults = results; } +// Get the backend representation. + +Bfunction* +Function::get_or_make_decl(Gogo* gogo, Named_object* no) +{ + if (this->fndecl_ == NULL) + { + std::string asm_name; + bool is_visible = false; + if (no->package() != NULL) + ; + else if (this->enclosing_ != NULL || Gogo::is_thunk(no)) + ; + else if (Gogo::unpack_hidden_name(no->name()) == "init" + && !this->type_->is_method()) + ; + else if (Gogo::unpack_hidden_name(no->name()) == "main" + && gogo->is_main_package()) + is_visible = true; + // Methods have to be public even if they are hidden because + // they can be pulled into type descriptors when using + // anonymous fields. + else if (!Gogo::is_hidden_name(no->name()) + || this->type_->is_method()) + { + if (!this->is_unnamed_type_stub_method_) + is_visible = true; + std::string pkgpath = gogo->pkgpath_symbol(); + if (this->type_->is_method() + && Gogo::is_hidden_name(no->name()) + && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath()) + { + // This is a method we created for an unexported + // method of an imported embedded type. We need to + // use the pkgpath of the imported package to avoid + // a possible name collision. See bug478 for a test + // case. + pkgpath = Gogo::hidden_name_pkgpath(no->name()); + pkgpath = Gogo::pkgpath_for_symbol(pkgpath); + } + + asm_name = pkgpath; + asm_name.append(1, '.'); + asm_name.append(Gogo::unpack_hidden_name(no->name())); + if (this->type_->is_method()) + { + asm_name.append(1, '.'); + Type* rtype = this->type_->receiver()->type(); + asm_name.append(rtype->mangled_name(gogo)); + } + } + + // If a function calls the predeclared recover function, we + // can't inline it, because recover behaves differently in a + // function passed directly to defer. If this is a recover + // thunk that we built to test whether a function can be + // recovered, we can't inline it, because that will mess up + // our return address comparison. + bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_); + + // If this is a thunk created to call a function which calls + // the predeclared recover function, we need to disable + // stack splitting for the thunk. + bool disable_split_stack = this->is_recover_thunk_; + + Btype* functype = this->type_->get_backend_fntype(gogo); + this->fndecl_ = + gogo->backend()->function(functype, no->get_id(gogo), asm_name, + is_visible, false, is_inlinable, + disable_split_stack, + this->in_unique_section_, this->location()); + } + return this->fndecl_; +} + // Class Block. Block::Block(Block* enclosing, Location location) @@ -5110,6 +5207,75 @@ go_unreachable(); } + +// Return the external identifier for this object. + +std::string +Named_object::get_id(Gogo* gogo) +{ + go_assert(!this->is_variable() && !this->is_result_variable()); + std::string decl_name; + if (this->is_function_declaration() + && !this->func_declaration_value()->asm_name().empty()) + decl_name = this->func_declaration_value()->asm_name(); + else if (this->is_type() + && Linemap::is_predeclared_location(this->type_value()->location())) + { + // We don't need the package name for builtin types. + decl_name = Gogo::unpack_hidden_name(this->name_); + } + else + { + std::string package_name; + if (this->package_ == NULL) + package_name = gogo->package_name(); + else + package_name = this->package_->package_name(); + + // Note that this will be misleading if this is an unexported + // method generated for an embedded imported type. In that case + // the unexported method should have the package name of the + // package from which it is imported, but we are going to give + // it our package name. Fixing this would require knowing the + // package name, but we only know the package path. It might be + // better to use package paths here anyhow. This doesn't affect + // the assembler code, because we always set that name in + // Function::get_or_make_decl anyhow. FIXME. + + decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_); + + Function_type* fntype; + if (this->is_function()) + fntype = this->func_value()->type(); + else if (this->is_function_declaration()) + fntype = this->func_declaration_value()->type(); + else + fntype = NULL; + if (fntype != NULL && fntype->is_method()) + { + decl_name.push_back('.'); + decl_name.append(fntype->receiver()->type()->mangled_name(gogo)); + } + } + if (this->is_type()) + { + unsigned int index; + const Named_object* in_function = this->type_value()->in_function(&index); + if (in_function != NULL) + { + decl_name += '$' + Gogo::unpack_hidden_name(in_function->name()); + if (index > 0) + { + char buf[30]; + snprintf(buf, sizeof buf, "%u", index); + decl_name += '$'; + decl_name += buf; + } + } + } + return decl_name; +} + // Class Bindings. Bindings::Bindings(Bindings* enclosing) diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/gogo.h gcc-4.8.2/gcc/go/gofrontend/gogo.h --- gcc-4.8.2.orig/gcc/go/gofrontend/gogo.h 2013-09-28 20:23:56.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/gogo.h 2014-03-30 20:21:40.680929667 +0000 @@ -48,6 +48,7 @@ class Bblock; class Bvariable; class Blabel; +class Bfunction; // This file declares the basic classes used to hold the internal // representation of Go which is built by the parser. @@ -952,6 +953,15 @@ this->nointerface_ = true; } + // Record that this function is a stub method created for an unnamed + // type. + void + set_is_unnamed_type_stub_method() + { + go_assert(this->is_method()); + this->is_unnamed_type_stub_method_ = true; + } + // Add a new field to the closure variable. void add_closure_field(Named_object* var, Location loc) @@ -1089,17 +1099,13 @@ this->descriptor_ = descriptor; } - // Return the function's decl given an identifier. - tree - get_or_make_decl(Gogo*, Named_object*, tree id); + // Return the backend representation. + Bfunction* + get_or_make_decl(Gogo*, Named_object*); // Return the function's decl after it has been built. tree - get_decl() const - { - go_assert(this->fndecl_ != NULL); - return this->fndecl_; - } + get_decl() const; // Set the function decl to hold a tree of the function code. void @@ -1170,7 +1176,7 @@ // The function descriptor, if any. Expression* descriptor_; // The function decl. - tree fndecl_; + Bfunction* fndecl_; // The defer stack variable. A pointer to this variable is used to // distinguish the defer stack for one function from another. This // is NULL unless we actually need a defer stack. @@ -1181,6 +1187,9 @@ bool results_are_named_ : 1; // True if this method should not be included in the type descriptor. bool nointerface_ : 1; + // True if this function is a stub method created for an unnamed + // type. + bool is_unnamed_type_stub_method_ : 1; // True if this function calls the predeclared recover function. bool calls_recover_ : 1; // True if this a thunk built for a function which calls recover. @@ -1265,9 +1274,9 @@ has_descriptor() const { return this->descriptor_ != NULL; } - // Return a decl for the function given an identifier. - tree - get_or_make_decl(Gogo*, Named_object*, tree id); + // Return a backend representation. + Bfunction* + get_or_make_decl(Gogo*, Named_object*); // If there is a descriptor, build it into the backend // representation. @@ -1290,7 +1299,7 @@ // The function descriptor, if any. Expression* descriptor_; // The function decl if needed. - tree fndecl_; + Bfunction* fndecl_; }; // A variable. @@ -2181,8 +2190,8 @@ Bvariable* get_backend_variable(Gogo*, Named_object* function); - // Return a tree for the external identifier for this object. - tree + // Return the external identifier for this object. + std::string get_id(Gogo*); // Return a tree representing this object. diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/import.h gcc-4.8.2/gcc/go/gofrontend/import.h --- gcc-4.8.2.orig/gcc/go/gofrontend/import.h 2012-10-31 00:38:49.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/import.h 2014-03-30 20:21:40.684263111 +0000 @@ -149,6 +149,11 @@ location() const { return this->location_; } + // Return the package we are importing. + Package* + package() const + { return this->package_; } + // Return the next character. int peek_char() diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/lex.cc gcc-4.8.2/gcc/go/gofrontend/lex.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/lex.cc 2012-12-03 06:57:04.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/lex.cc 2014-03-30 20:21:40.684263111 +0000 @@ -873,7 +873,28 @@ && (cc < 'a' || cc > 'z') && cc != '_' && (cc < '0' || cc > '9')) - break; + { + // Check for an invalid character here, as we get better + // error behaviour if we swallow them as part of the + // identifier we are building. + if ((cc >= ' ' && cc < 0x7f) + || cc == '\t' + || cc == '\r' + || cc == '\n') + break; + + this->lineoff_ = p - this->linebuf_; + error_at(this->location(), + "invalid character 0x%x in identifier", + cc); + if (!has_non_ascii_char) + { + buf.assign(pstart, p - pstart); + has_non_ascii_char = true; + } + if (!Lex::is_invalid_identifier(buf)) + buf.append("$INVALID$"); + } ++p; if (is_first) { diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/parse.cc gcc-4.8.2/gcc/go/gofrontend/parse.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/parse.cc 2013-10-08 23:54:31.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/parse.cc 2014-03-30 20:21:40.684263111 +0000 @@ -744,6 +744,8 @@ return NULL; Parse::Names names; + if (receiver != NULL) + names[receiver->name()] = receiver; if (params != NULL) this->check_signature_names(params, &names); if (results != NULL) diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/runtime.cc gcc-4.8.2/gcc/go/gofrontend/runtime.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/runtime.cc 2012-12-21 15:59:27.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/runtime.cc 2014-03-30 20:21:40.684263111 +0000 @@ -42,6 +42,8 @@ RFT_RUNE, // Go type float64, C type double. RFT_FLOAT64, + // Go type complex64, C type __complex float. + RFT_COMPLEX64, // Go type complex128, C type __complex double. RFT_COMPLEX128, // Go type string, C type struct __go_string. @@ -126,6 +128,10 @@ t = Type::lookup_float_type("float64"); break; + case RFT_COMPLEX64: + t = Type::lookup_complex_type("complex64"); + break; + case RFT_COMPLEX128: t = Type::lookup_complex_type("complex128"); break; @@ -216,6 +222,7 @@ case RFT_UINTPTR: case RFT_RUNE: case RFT_FLOAT64: + case RFT_COMPLEX64: case RFT_COMPLEX128: case RFT_STRING: case RFT_POINTER: diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/runtime.def gcc-4.8.2/gcc/go/gofrontend/runtime.def --- gcc-4.8.2.orig/gcc/go/gofrontend/runtime.def 2013-06-18 23:50:42.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/runtime.def 2014-03-30 20:21:40.684263111 +0000 @@ -68,6 +68,12 @@ P1(STRING), R1(SLICE)) +// Complex division. +DEF_GO_RUNTIME(COMPLEX64_DIV, "__go_complex64_div", + P2(COMPLEX64, COMPLEX64), R1(COMPLEX64)) +DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div", + P2(COMPLEX128, COMPLEX128), R1(COMPLEX128)) + // Make a slice. DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE)) DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR), diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/types.cc gcc-4.8.2/gcc/go/gofrontend/types.cc --- gcc-4.8.2.orig/gcc/go/gofrontend/types.cc 2013-10-02 19:22:30.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/types.cc 2014-03-30 20:21:40.684263111 +0000 @@ -1834,7 +1834,9 @@ bloc); gogo->start_block(bloc); - if (this->struct_type() != NULL) + if (name != NULL && name->real_type()->named_type() != NULL) + this->write_named_hash(gogo, name, hash_fntype, equal_fntype); + else if (this->struct_type() != NULL) this->struct_type()->write_hash_function(gogo, name, hash_fntype, equal_fntype); else if (this->array_type() != NULL) @@ -1852,7 +1854,9 @@ false, bloc); gogo->start_block(bloc); - if (this->struct_type() != NULL) + if (name != NULL && name->real_type()->named_type() != NULL) + this->write_named_equal(gogo, name); + else if (this->struct_type() != NULL) this->struct_type()->write_equal_function(gogo, name); else if (this->array_type() != NULL) this->array_type()->write_equal_function(gogo, name); @@ -1865,6 +1869,100 @@ gogo->finish_function(bloc); } +// Write a hash function that simply calls the hash function for a +// named type. This is used when one named type is defined as +// another. This ensures that this case works when the other named +// type is defined in another package and relies on calling hash +// functions defined only in that package. + +void +Type::write_named_hash(Gogo* gogo, Named_type* name, + Function_type* hash_fntype, Function_type* equal_fntype) +{ + Location bloc = Linemap::predeclared_location(); + + Named_type* base_type = name->real_type()->named_type(); + go_assert(base_type != NULL); + + // The pointer to the type we are going to hash. This is an + // unsafe.Pointer. + Named_object* key_arg = gogo->lookup("key", NULL); + go_assert(key_arg != NULL); + + // The size of the type we are going to hash. + Named_object* keysz_arg = gogo->lookup("key_size", NULL); + go_assert(keysz_arg != NULL); + + Named_object* hash_fn; + Named_object* equal_fn; + name->real_type()->type_functions(gogo, base_type, hash_fntype, equal_fntype, + &hash_fn, &equal_fn); + + // Call the hash function for the base type. + Expression* key_ref = Expression::make_var_reference(key_arg, bloc); + Expression* keysz_ref = Expression::make_var_reference(keysz_arg, bloc); + Expression_list* args = new Expression_list(); + args->push_back(key_ref); + args->push_back(keysz_ref); + Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc); + Expression* call = Expression::make_call(func, args, false, bloc); + + // Return the hash of the base type. + Expression_list* vals = new Expression_list(); + vals->push_back(call); + Statement* s = Statement::make_return_statement(vals, bloc); + gogo->add_statement(s); +} + +// Write an equality function that simply calls the equality function +// for a named type. This is used when one named type is defined as +// another. This ensures that this case works when the other named +// type is defined in another package and relies on calling equality +// functions defined only in that package. + +void +Type::write_named_equal(Gogo* gogo, Named_type* name) +{ + Location bloc = Linemap::predeclared_location(); + + // The pointers to the types we are going to compare. These have + // type unsafe.Pointer. + Named_object* key1_arg = gogo->lookup("key1", NULL); + Named_object* key2_arg = gogo->lookup("key2", NULL); + go_assert(key1_arg != NULL && key2_arg != NULL); + + Named_type* base_type = name->real_type()->named_type(); + go_assert(base_type != NULL); + + // Build temporaries with the base type. + Type* pt = Type::make_pointer_type(base_type); + + Expression* ref = Expression::make_var_reference(key1_arg, bloc); + ref = Expression::make_cast(pt, ref, bloc); + Temporary_statement* p1 = Statement::make_temporary(pt, ref, bloc); + gogo->add_statement(p1); + + ref = Expression::make_var_reference(key2_arg, bloc); + ref = Expression::make_cast(pt, ref, bloc); + Temporary_statement* p2 = Statement::make_temporary(pt, ref, bloc); + gogo->add_statement(p2); + + // Compare the values for equality. + Expression* t1 = Expression::make_temporary_reference(p1, bloc); + t1 = Expression::make_unary(OPERATOR_MULT, t1, bloc); + + Expression* t2 = Expression::make_temporary_reference(p2, bloc); + t2 = Expression::make_unary(OPERATOR_MULT, t2, bloc); + + Expression* cond = Expression::make_binary(OPERATOR_EQEQ, t1, t2, bloc); + + // Return the equality comparison. + Expression_list* vals = new Expression_list(); + vals->push_back(cond); + Statement* s = Statement::make_return_statement(vals, bloc); + gogo->add_statement(s); +} + // Return a composite literal for the type descriptor for a plain type // of kind RUNTIME_TYPE_KIND named NAME. @@ -2164,26 +2262,9 @@ ++p; go_assert(p->is_field_name("typ")); - if (!only_value_methods && m->is_value_method()) - { - // This is a value method on a pointer type. Change the type of - // the method to use a pointer receiver. The implementation - // always uses a pointer receiver anyhow. - Type* rtype = mtype->receiver()->type(); - Type* prtype = Type::make_pointer_type(rtype); - Typed_identifier* receiver = - new Typed_identifier(mtype->receiver()->name(), prtype, - mtype->receiver()->location()); - mtype = Type::make_function_type(receiver, - (mtype->parameters() == NULL - ? NULL - : mtype->parameters()->copy()), - (mtype->results() == NULL - ? NULL - : mtype->results()->copy()), - mtype->location()); - } - vals->push_back(Expression::make_type_descriptor(mtype, bloc)); + bool want_pointer_receiver = !only_value_methods && m->is_value_method(); + nonmethod_type = mtype->copy_with_receiver_as_param(want_pointer_receiver); + vals->push_back(Expression::make_type_descriptor(nonmethod_type, bloc)); ++p; go_assert(p->is_field_name("tfn")); @@ -3383,6 +3464,68 @@ // Get the backend representation for a function type. Btype* +Function_type::get_backend_fntype(Gogo* gogo) +{ + if (this->fnbtype_ == NULL) + { + Backend::Btyped_identifier breceiver; + if (this->receiver_ != NULL) + { + breceiver.name = Gogo::unpack_hidden_name(this->receiver_->name()); + + // We always pass the address of the receiver parameter, in + // order to make interface calls work with unknown types. + Type* rtype = this->receiver_->type(); + if (rtype->points_to() == NULL) + rtype = Type::make_pointer_type(rtype); + breceiver.btype = rtype->get_backend(gogo); + breceiver.location = this->receiver_->location(); + } + + std::vector bparameters; + if (this->parameters_ != NULL) + { + bparameters.resize(this->parameters_->size()); + size_t i = 0; + for (Typed_identifier_list::const_iterator p = + this->parameters_->begin(); p != this->parameters_->end(); + ++p, ++i) + { + bparameters[i].name = Gogo::unpack_hidden_name(p->name()); + bparameters[i].btype = p->type()->get_backend(gogo); + bparameters[i].location = p->location(); + } + go_assert(i == bparameters.size()); + } + + std::vector bresults; + if (this->results_ != NULL) + { + bresults.resize(this->results_->size()); + size_t i = 0; + for (Typed_identifier_list::const_iterator p = + this->results_->begin(); p != this->results_->end(); + ++p, ++i) + { + bresults[i].name = Gogo::unpack_hidden_name(p->name()); + bresults[i].btype = p->type()->get_backend(gogo); + bresults[i].location = p->location(); + } + go_assert(i == bresults.size()); + } + + this->fnbtype_ = gogo->backend()->function_type(breceiver, bparameters, + bresults, + this->location()); + + } + + return this->fnbtype_; +} + +// Get the backend representation for a Go function type. + +Btype* Function_type::do_get_backend(Gogo* gogo) { // When we do anything with a function value other than call it, it @@ -3395,57 +3538,9 @@ gogo->backend()->placeholder_struct_type("__go_descriptor", loc); Btype* ptr_struct_type = gogo->backend()->pointer_type(struct_type); - Backend::Btyped_identifier breceiver; - if (this->receiver_ != NULL) - { - breceiver.name = Gogo::unpack_hidden_name(this->receiver_->name()); - - // We always pass the address of the receiver parameter, in - // order to make interface calls work with unknown types. - Type* rtype = this->receiver_->type(); - if (rtype->points_to() == NULL) - rtype = Type::make_pointer_type(rtype); - breceiver.btype = rtype->get_backend(gogo); - breceiver.location = this->receiver_->location(); - } - - std::vector bparameters; - if (this->parameters_ != NULL) - { - bparameters.resize(this->parameters_->size()); - size_t i = 0; - for (Typed_identifier_list::const_iterator p = this->parameters_->begin(); - p != this->parameters_->end(); - ++p, ++i) - { - bparameters[i].name = Gogo::unpack_hidden_name(p->name()); - bparameters[i].btype = p->type()->get_backend(gogo); - bparameters[i].location = p->location(); - } - go_assert(i == bparameters.size()); - } - - std::vector bresults; - if (this->results_ != NULL) - { - bresults.resize(this->results_->size()); - size_t i = 0; - for (Typed_identifier_list::const_iterator p = this->results_->begin(); - p != this->results_->end(); - ++p, ++i) - { - bresults[i].name = Gogo::unpack_hidden_name(p->name()); - bresults[i].btype = p->type()->get_backend(gogo); - bresults[i].location = p->location(); - } - go_assert(i == bresults.size()); - } - - Btype* fntype = gogo->backend()->function_type(breceiver, bparameters, - bresults, loc); std::vector fields(1); fields[0].name = "code"; - fields[0].btype = fntype; + fields[0].btype = this->get_backend_fntype(gogo); fields[0].location = loc; if (!gogo->backend()->set_placeholder_struct_type(struct_type, fields)) return gogo->backend()->error_type(); @@ -3821,6 +3916,32 @@ return ret; } +// Make a copy of a function type with the receiver as the first +// parameter. + +Function_type* +Function_type::copy_with_receiver_as_param(bool want_pointer_receiver) const +{ + go_assert(this->is_method()); + Typed_identifier_list* new_params = new Typed_identifier_list(); + Type* rtype = this->receiver_->type(); + if (want_pointer_receiver) + rtype = Type::make_pointer_type(rtype); + Typed_identifier receiver(this->receiver_->name(), rtype, + this->receiver_->location()); + new_params->push_back(receiver); + const Typed_identifier_list* orig_params = this->parameters_; + if (orig_params != NULL && !orig_params->empty()) + { + for (Typed_identifier_list::const_iterator p = orig_params->begin(); + p != orig_params->end(); + ++p) + new_params->push_back(*p); + } + return Type::make_function_type(NULL, new_params, this->results_, + this->location_); +} + // Make a copy of a function type ignoring any receiver and adding a // closure parameter. @@ -4195,7 +4316,8 @@ // This is a horrible hack caused by the fact that we don't pack // the names of builtin types. FIXME. - if (nt != NULL + if (!this->is_imported_ + && nt != NULL && nt->is_builtin() && nt->name() == Gogo::unpack_hidden_name(name)) return true; @@ -4204,6 +4326,36 @@ } } +// Return whether this field is an unexported field named NAME. + +bool +Struct_field::is_unexported_field_name(Gogo* gogo, + const std::string& name) const +{ + const std::string& field_name(this->field_name()); + if (Gogo::is_hidden_name(field_name) + && name == Gogo::unpack_hidden_name(field_name) + && gogo->pack_hidden_name(name, false) != field_name) + return true; + + // Check for the name of a builtin type. This is like the test in + // is_field_name, only there we return false if this->is_imported_, + // and here we return true. + if (this->is_imported_ && this->is_anonymous()) + { + Type* t = this->typed_identifier_.type(); + if (t->points_to() != NULL) + t = t->points_to(); + Named_type* nt = t->named_type(); + if (nt != NULL + && nt->is_builtin() + && nt->name() == Gogo::unpack_hidden_name(name)) + return true; + } + + return false; +} + // Return whether this field is an embedded built-in type. bool @@ -4264,12 +4416,7 @@ ++p) { Type* t = p->type(); - if (t->is_undefined()) - { - error_at(p->location(), "struct field type is incomplete"); - p->set_type(Type::make_error_type()); - } - else if (p->is_anonymous()) + if (p->is_anonymous()) { if (t->named_type() != NULL && t->points_to() != NULL) { @@ -4641,13 +4788,8 @@ for (Struct_field_list::const_iterator pf = fields->begin(); pf != fields->end(); ++pf) - { - const std::string& field_name(pf->field_name()); - if (Gogo::is_hidden_name(field_name) - && name == Gogo::unpack_hidden_name(field_name) - && gogo->pack_hidden_name(name, false) != field_name) - return true; - } + if (pf->is_unexported_field_name(gogo, name)) + return true; } return false; } @@ -5250,6 +5392,7 @@ Type* ftype = imp->read_type(); Struct_field sf(Typed_identifier(name, ftype, imp->location())); + sf.set_is_imported(); if (imp->peek_char() == ' ') { @@ -9022,6 +9165,8 @@ fntype->is_varargs(), location); gogo->finish_function(fntype->location()); + if (type->named_type() == NULL && stub->is_function()) + stub->func_value()->set_is_unnamed_type_stub_method(); if (m->nointerface() && stub->is_function()) stub->func_value()->set_nointerface(); } @@ -9289,7 +9434,9 @@ else { bool is_unexported; - if (!Gogo::is_hidden_name(name)) + // The test for 'a' and 'z' is to handle builtin names, + // which are not hidden. + if (!Gogo::is_hidden_name(name) && (name[0] < 'a' || name[0] > 'z')) is_unexported = false; else { diff -Naur gcc-4.8.2.orig/gcc/go/gofrontend/types.h gcc-4.8.2/gcc/go/gofrontend/types.h --- gcc-4.8.2.orig/gcc/go/gofrontend/types.h 2013-09-18 21:54:08.000000000 +0000 +++ gcc-4.8.2/gcc/go/gofrontend/types.h 2014-03-30 20:21:40.687596554 +0000 @@ -1138,6 +1138,13 @@ Function_type* equal_fntype, Named_object** hash_fn, Named_object** equal_fn); + void + write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype, + Function_type* equal_fntype); + + void + write_named_equal(Gogo*, Named_type*); + // Build a composite literal for the uncommon type information. Expression* uncommon_type_constructor(Gogo*, Type* uncommon_type, @@ -1717,7 +1724,8 @@ Typed_identifier_list* results, Location location) : Type(TYPE_FUNCTION), receiver_(receiver), parameters_(parameters), results_(results), - location_(location), is_varargs_(false), is_builtin_(false) + location_(location), is_varargs_(false), is_builtin_(false), + fnbtype_(NULL) { } // Get the receiver. @@ -1789,6 +1797,12 @@ Function_type* copy_with_receiver(Type*) const; + // Return a copy of this type with the receiver treated as the first + // parameter. If WANT_POINTER_RECEIVER is true, the receiver is + // forced to be a pointer. + Function_type* + copy_with_receiver_as_param(bool want_pointer_receiver) const; + // Return a copy of this type ignoring any receiver and using dummy // names for all parameters. This is used for thunks for method // values. @@ -1798,6 +1812,11 @@ static Type* make_function_type_descriptor_type(); + // Return the backend representation of this function type. This is used + // as the real type of a backend function declaration or defintion. + Btype* + get_backend_fntype(Gogo*); + protected: int do_traverse(Traverse*); @@ -1851,6 +1870,9 @@ // Whether this is a special builtin function which can not simply // be called. This is used for len, cap, etc. bool is_builtin_; + // The backend representation of this type for backend function + // declarations and definitions. + Btype* fnbtype_; }; // The type of a pointer. @@ -1915,7 +1937,7 @@ { public: explicit Struct_field(const Typed_identifier& typed_identifier) - : typed_identifier_(typed_identifier), tag_(NULL) + : typed_identifier_(typed_identifier), tag_(NULL), is_imported_(false) { } // The field name. @@ -1926,6 +1948,10 @@ bool is_field_name(const std::string& name) const; + // Return whether this struct field is an unexported field named NAME. + bool + is_unexported_field_name(Gogo*, const std::string& name) const; + // Return whether this struct field is an embedded built-in type. bool is_embedded_builtin(Gogo*) const; @@ -1963,6 +1989,11 @@ set_tag(const std::string& tag) { this->tag_ = new std::string(tag); } + // Record that this field is defined in an imported struct. + void + set_is_imported() + { this->is_imported_ = true; } + // Set the type. This is only used in error cases. void set_type(Type* type) @@ -1973,6 +2004,8 @@ Typed_identifier typed_identifier_; // The field tag. This is NULL if the field has no tag. std::string* tag_; + // Whether this field is defined in an imported struct. + bool is_imported_; }; // A list of struct fields. diff -Naur gcc-4.8.2.orig/gcc/graphite-clast-to-gimple.c gcc-4.8.2/gcc/graphite-clast-to-gimple.c --- gcc-4.8.2.orig/gcc/graphite-clast-to-gimple.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/graphite-clast-to-gimple.c 2014-03-30 20:28:17.513930767 +0000 @@ -1170,8 +1170,11 @@ redirect_edge_succ_nodup (next_e, after); set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src); + isl_set *domain = isl_set_from_cloog_domain (stmt->domain); + int scheduling_dim = isl_set_n_dim (domain); + if (flag_loop_parallelize_all - && loop_is_parallel_p (loop, bb_pbb_mapping, level)) + && loop_is_parallel_p (loop, bb_pbb_mapping, scheduling_dim)) loop->can_be_parallel = true; return last_e; diff -Naur gcc-4.8.2.orig/gcc/graphite-dependences.c gcc-4.8.2/gcc/graphite-dependences.c --- gcc-4.8.2.orig/gcc/graphite-dependences.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/graphite-dependences.c 2014-03-30 20:28:17.513930767 +0000 @@ -297,7 +297,7 @@ int depth) { bool res; - int idx, i; + int i; isl_space *space; isl_map *lex, *x; isl_constraint *ineq; @@ -312,13 +312,12 @@ space = isl_map_get_space (x); ineq = isl_inequality_alloc (isl_local_space_from_space (space)); - idx = 2 * depth + 1; - for (i = 0; i < idx; i++) + for (i = 0; i < depth - 1; i++) lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i); /* in + 1 <= out */ - ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, idx, 1); - ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, idx, -1); + ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1); + ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1); ineq = isl_constraint_set_constant_si (ineq, -1); lex = isl_map_add_constraint (lex, ineq); x = isl_map_intersect (x, lex); diff -Naur gcc-4.8.2.orig/gcc/ifcvt.c gcc-4.8.2/gcc/ifcvt.c --- gcc-4.8.2.orig/gcc/ifcvt.c 2013-04-12 05:39:49.000000000 +0000 +++ gcc-4.8.2/gcc/ifcvt.c 2014-03-30 20:21:40.687596554 +0000 @@ -115,7 +115,11 @@ while (1) { - if (CALL_P (insn) || NONJUMP_INSN_P (insn)) + if ((CALL_P (insn) || NONJUMP_INSN_P (insn)) + /* Don't count USE/CLOBBER insns, flow_find_cross_jump etc. + don't count them either and we need consistency. */ + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER) count++; if (insn == BB_END (bb)) @@ -505,7 +509,10 @@ n_insns -= 2 * n_matching; } - if (then_start && else_start) + if (then_start + && else_start + && then_n_insns > n_matching + && else_n_insns > n_matching) { int longest_match = MIN (then_n_insns - n_matching, else_n_insns - n_matching); diff -Naur gcc-4.8.2.orig/gcc/ipa-cp.c gcc-4.8.2/gcc/ipa-cp.c --- gcc-4.8.2.orig/gcc/ipa-cp.c 2013-06-12 13:17:03.000000000 +0000 +++ gcc-4.8.2/gcc/ipa-cp.c 2014-03-30 20:21:40.687596554 +0000 @@ -444,6 +444,9 @@ reason = "not a tree_versionable_function"; else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) reason = "insufficient body availability"; + else if (!opt_for_fn (node->symbol.decl, optimize) + || !opt_for_fn (node->symbol.decl, flag_ipa_cp)) + reason = "non-optimized function"; if (reason && dump_file && !node->alias && !node->thunk.thunk_p) fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n", @@ -3119,6 +3122,7 @@ struct cgraph_node *node) { struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller); + struct ipa_node_params *orig_node_info; struct ipa_agg_replacement_value *aggval; int i, ec, count; @@ -3133,6 +3137,7 @@ if (aggval->index >= ec) return false; + orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node); if (orig_caller_info->ipcp_orig_node) orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node); @@ -3150,7 +3155,7 @@ if (!interesting) continue; - plats = ipa_get_parm_lattices (orig_caller_info, aggval->index); + plats = ipa_get_parm_lattices (orig_node_info, aggval->index); if (plats->aggs_bottom) return false; diff -Naur gcc-4.8.2.orig/gcc/ipa-prop.c gcc-4.8.2/gcc/ipa-prop.c --- gcc-4.8.2.orig/gcc/ipa-prop.c 2013-06-24 12:57:52.000000000 +0000 +++ gcc-4.8.2/gcc/ipa-prop.c 2014-03-30 20:21:40.690929996 +0000 @@ -623,16 +623,22 @@ if (parm_ainfo && parm_ainfo->parm_modified) return false; - gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE); - ao_ref_init (&refd, parm_load); - /* We can cache visited statements only when parm_ainfo is available and when - we are looking at a naked load of the whole parameter. */ - if (!parm_ainfo || TREE_CODE (parm_load) != PARM_DECL) - visited_stmts = NULL; + if (optimize) + { + gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE); + ao_ref_init (&refd, parm_load); + /* We can cache visited statements only when parm_ainfo is available and + when we are looking at a naked load of the whole parameter. */ + if (!parm_ainfo || TREE_CODE (parm_load) != PARM_DECL) + visited_stmts = NULL; + else + visited_stmts = &parm_ainfo->parm_visited_statements; + walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified, + visited_stmts); + } else - visited_stmts = &parm_ainfo->parm_visited_statements; - walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified, - visited_stmts); + modified = true; + if (parm_ainfo && modified) parm_ainfo->parm_modified = true; return !modified; @@ -740,7 +746,7 @@ ipa_load_from_parm_agg_1 (vec descriptors, struct param_analysis_info *parms_ainfo, gimple stmt, tree op, int *index_p, HOST_WIDE_INT *offset_p, - bool *by_ref_p) + HOST_WIDE_INT *size_p, bool *by_ref_p) { int index; HOST_WIDE_INT size, max_size; @@ -758,6 +764,8 @@ { *index_p = index; *by_ref_p = false; + if (size_p) + *size_p = size; return true; } return false; @@ -800,6 +808,8 @@ { *index_p = index; *by_ref_p = true; + if (size_p) + *size_p = size; return true; } return false; @@ -814,7 +824,7 @@ bool *by_ref_p) { return ipa_load_from_parm_agg_1 (info->descriptors, NULL, stmt, op, index_p, - offset_p, by_ref_p); + offset_p, NULL, by_ref_p); } /* Given that an actual argument is an SSA_NAME (given in NAME) and is a result @@ -1051,7 +1061,8 @@ return; parm = TREE_OPERAND (expr, 0); index = ipa_get_param_decl_index (info, SSA_NAME_VAR (parm)); - gcc_assert (index >= 0); + if (index < 0) + return; cond_bb = single_pred (assign_bb); cond = last_stmt (cond_bb); @@ -1462,6 +1473,9 @@ { struct cgraph_edge *cs; + if (!optimize) + return; + for (cs = node->callees; cs; cs = cs->next_callee) { struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee, @@ -1646,7 +1660,7 @@ if (gimple_assign_single_p (def) && ipa_load_from_parm_agg_1 (info->descriptors, parms_ainfo, def, gimple_assign_rhs1 (def), &index, &offset, - &by_ref)) + NULL, &by_ref)) { struct cgraph_edge *cs = ipa_note_param_call (node, index, call); cs->indirect_info->offset = offset; @@ -1847,8 +1861,7 @@ passed in DATA. */ static bool -visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, - tree op, void *data) +visit_ref_for_mod_analysis (gimple, tree op, tree, void *data) { struct ipa_node_params *info = (struct ipa_node_params *) data; @@ -2126,7 +2139,6 @@ we may create the first reference to the object in the unit. */ if (!callee || callee->global.inlined_to) { - struct cgraph_node *first_clone = callee; /* We are better to ensure we can refer to it. In the case of static functions we are out of luck, since we already @@ -2142,31 +2154,7 @@ xstrdup (cgraph_node_name (ie->callee)), ie->callee->uid); return NULL; } - - /* Create symbol table node. Even if inline clone exists, we can not take - it as a target of non-inlined call. */ - callee = cgraph_create_node (target); - - /* OK, we previously inlined the function, then removed the offline copy and - now we want it back for external call. This can happen when devirtualizing - while inlining function called once that happens after extern inlined and - virtuals are already removed. In this case introduce the external node - and make it available for call. */ - if (first_clone) - { - first_clone->clone_of = callee; - callee->clones = first_clone; - symtab_prevail_in_asm_name_hash ((symtab_node)callee); - symtab_insert_node_to_hashtable ((symtab_node)callee); - if (dump_file) - fprintf (dump_file, "ipa-prop: Introduced new external node " - "(%s/%i) and turned into root of the clone tree.\n", - xstrdup (cgraph_node_name (callee)), callee->uid); - } - else if (dump_file) - fprintf (dump_file, "ipa-prop: Introduced new external node " - "(%s/%i).\n", - xstrdup (cgraph_node_name (callee)), callee->uid); + callee = cgraph_get_create_real_symbol_node (target); } ipa_check_create_node_params (); @@ -3902,7 +3890,7 @@ struct ipa_agg_replacement_value *v; gimple stmt = gsi_stmt (gsi); tree rhs, val, t; - HOST_WIDE_INT offset; + HOST_WIDE_INT offset, size; int index; bool by_ref, vce; @@ -3929,13 +3917,15 @@ continue; if (!ipa_load_from_parm_agg_1 (descriptors, parms_ainfo, stmt, - rhs, &index, &offset, &by_ref)) + rhs, &index, &offset, &size, &by_ref)) continue; for (v = aggval; v; v = v->next) if (v->index == index && v->offset == offset) break; - if (!v || v->by_ref != by_ref) + if (!v + || v->by_ref != by_ref + || tree_low_cst (TYPE_SIZE (TREE_TYPE (v->value)), 0) != size) continue; gcc_checking_assert (is_gimple_ip_invariant (v->value)); diff -Naur gcc-4.8.2.orig/gcc/ipa-pure-const.c gcc-4.8.2/gcc/ipa-pure-const.c --- gcc-4.8.2.orig/gcc/ipa-pure-const.c 2013-02-27 21:35:53.000000000 +0000 +++ gcc-4.8.2/gcc/ipa-pure-const.c 2014-03-30 20:21:40.690929996 +0000 @@ -588,7 +588,7 @@ /* Wrapper around check_decl for loads in local more. */ static bool -check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +check_load (gimple, tree op, tree, void *data) { if (DECL_P (op)) check_decl ((funct_state)data, op, false, false); @@ -600,7 +600,7 @@ /* Wrapper around check_decl for stores in local more. */ static bool -check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +check_store (gimple, tree op, tree, void *data) { if (DECL_P (op)) check_decl ((funct_state)data, op, true, false); @@ -612,7 +612,7 @@ /* Wrapper around check_decl for loads in ipa mode. */ static bool -check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +check_ipa_load (gimple, tree op, tree, void *data) { if (DECL_P (op)) check_decl ((funct_state)data, op, false, true); @@ -624,7 +624,7 @@ /* Wrapper around check_decl for stores in ipa mode. */ static bool -check_ipa_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +check_ipa_store (gimple, tree op, tree, void *data) { if (DECL_P (op)) check_decl ((funct_state)data, op, true, true); diff -Naur gcc-4.8.2.orig/gcc/ipa-split.c gcc-4.8.2/gcc/ipa-split.c --- gcc-4.8.2.orig/gcc/ipa-split.c 2013-03-04 17:41:32.000000000 +0000 +++ gcc-4.8.2/gcc/ipa-split.c 2014-03-30 20:21:40.690929996 +0000 @@ -136,7 +136,7 @@ variable, check it if it is present in bitmap passed via DATA. */ static bool -test_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data) +test_nonssa_use (gimple, tree t, tree, void *data) { t = get_base_address (t); @@ -229,7 +229,7 @@ } if (gimple_code (stmt) == GIMPLE_LABEL && test_nonssa_use (stmt, gimple_label_label (stmt), - non_ssa_vars)) + NULL_TREE, non_ssa_vars)) { ok = false; goto done; @@ -258,7 +258,7 @@ if (virtual_operand_p (gimple_phi_result (stmt))) continue; if (TREE_CODE (op) != SSA_NAME - && test_nonssa_use (stmt, op, non_ssa_vars)) + && test_nonssa_use (stmt, op, op, non_ssa_vars)) { ok = false; goto done; @@ -670,7 +670,7 @@ Return true when access to T prevents splitting the function. */ static bool -mark_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data) +mark_nonssa_use (gimple, tree t, tree, void *data) { t = get_base_address (t); @@ -830,7 +830,7 @@ if (TREE_CODE (op) == SSA_NAME) bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op)); else - can_split &= !mark_nonssa_use (stmt, op, non_ssa_vars); + can_split &= !mark_nonssa_use (stmt, op, op, non_ssa_vars); } } return can_split; diff -Naur gcc-4.8.2.orig/gcc/ipa.c gcc-4.8.2/gcc/ipa.c --- gcc-4.8.2.orig/gcc/ipa.c 2013-01-17 11:43:14.000000000 +0000 +++ gcc-4.8.2/gcc/ipa.c 2014-03-30 20:21:40.687596554 +0000 @@ -359,6 +359,8 @@ { if (file) fprintf (file, " %s", cgraph_node_name (node)); + node->alias = false; + node->thunk.thunk_p = false; cgraph_node_remove_callees (node); ipa_remove_all_references (&node->symbol.ref_list); changed = true; diff -Naur gcc-4.8.2.orig/gcc/ira.c gcc-4.8.2/gcc/ira.c --- gcc-4.8.2.orig/gcc/ira.c 2013-06-20 21:15:52.000000000 +0000 +++ gcc-4.8.2/gcc/ira.c 2014-03-30 20:21:40.690929996 +0000 @@ -4742,6 +4742,18 @@ if (need_dce && optimize) run_fast_dce (); + /* Diagnose uses of the hard frame pointer when it is used as a global + register. Often we can get away with letting the user appropriate + the frame pointer, but we should let them know when code generation + makes that impossible. */ + if (global_regs[HARD_FRAME_POINTER_REGNUM] && frame_pointer_needed) + { + tree decl = global_regs_decl[HARD_FRAME_POINTER_REGNUM]; + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "frame pointer required, but reserved"); + inform (DECL_SOURCE_LOCATION (decl), "for %qD", decl); + } + timevar_pop (TV_IRA); } diff -Naur gcc-4.8.2.orig/gcc/loop-iv.c gcc-4.8.2/gcc/loop-iv.c --- gcc-4.8.2.orig/gcc/loop-iv.c 2013-04-23 19:36:20.000000000 +0000 +++ gcc-4.8.2/gcc/loop-iv.c 2014-03-30 20:21:40.690929996 +0000 @@ -425,7 +425,9 @@ && !iv->first_special) { rtx val = get_iv_value (iv, const0_rtx); - val = lowpart_subreg (mode, val, iv->extend_mode); + val = lowpart_subreg (mode, val, + iv->extend == IV_UNKNOWN_EXTEND + ? iv->mode : iv->extend_mode); iv->base = val; iv->extend = IV_UNKNOWN_EXTEND; @@ -465,8 +467,14 @@ && !iv->first_special) { rtx val = get_iv_value (iv, const0_rtx); + if (iv->extend_mode != iv->mode + && iv->extend != IV_UNKNOWN_EXTEND + && iv->extend != extend) + val = lowpart_subreg (iv->mode, val, iv->extend_mode); val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode, - val, iv->extend_mode); + val, + iv->extend == extend + ? iv->extend_mode : iv->mode); iv->base = val; iv->extend = IV_UNKNOWN_EXTEND; iv->mode = iv->extend_mode = mode; diff -Naur gcc-4.8.2.orig/gcc/loop-unswitch.c gcc-4.8.2/gcc/loop-unswitch.c --- gcc-4.8.2.orig/gcc/loop-unswitch.c 2013-02-13 11:42:04.000000000 +0000 +++ gcc-4.8.2/gcc/loop-unswitch.c 2014-03-30 20:21:40.690929996 +0000 @@ -191,6 +191,7 @@ if (!test) return NULL_RTX; + mode = VOIDmode; for (i = 0; i < 2; i++) { op[i] = XEXP (test, i); @@ -205,11 +206,15 @@ return NULL_RTX; op[i] = get_iv_value (&iv, const0_rtx); + if (iv.extend != IV_UNKNOWN_EXTEND + && iv.mode != iv.extend_mode) + op[i] = lowpart_subreg (iv.mode, op[i], iv.extend_mode); + if (mode == VOIDmode) + mode = iv.mode; + else + gcc_assert (mode == iv.mode); } - mode = GET_MODE (op[0]); - if (mode == VOIDmode) - mode = GET_MODE (op[1]); if (GET_MODE_CLASS (mode) == MODE_CC) { if (at != BB_END (bb)) diff -Naur gcc-4.8.2.orig/gcc/lra-coalesce.c gcc-4.8.2/gcc/lra-coalesce.c --- gcc-4.8.2.orig/gcc/lra-coalesce.c 2013-05-02 17:46:58.000000000 +0000 +++ gcc-4.8.2/gcc/lra-coalesce.c 2014-03-30 20:21:40.694263438 +0000 @@ -221,9 +221,12 @@ basic_block bb; rtx mv, set, insn, next, *sorted_moves; int i, mv_num, sregno, dregno; + unsigned int regno; int coalesced_moves; int max_regno = max_reg_num (); bitmap_head involved_insns_bitmap; + bitmap_head result_pseudo_vals_bitmap; + bitmap_iterator bi; timevar_push (TV_LRA_COALESCE); @@ -318,6 +321,34 @@ } } } + /* If we have situation after inheritance pass: + + r1 <- ... insn originally setting p1 + i1 <- r1 setting inheritance i1 from reload r1 + ... + ... <- ... p2 ... dead p2 + .. + p1 <- i1 + r2 <- i1 + ...<- ... r2 ... + + And we are coalescing p1 and p2 using p1. In this case i1 and p1 + should have different values, otherwise they can get the same + hard reg and this is wrong for insn using p2 before coalescing. + So invalidate such inheritance pseudo values. */ + bitmap_initialize (&result_pseudo_vals_bitmap, ®_obstack); + EXECUTE_IF_SET_IN_BITMAP (&coalesced_pseudos_bitmap, 0, regno, bi) + bitmap_set_bit (&result_pseudo_vals_bitmap, + lra_reg_info[first_coalesced_pseudo[regno]].val); + EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi) + if (bitmap_bit_p (&result_pseudo_vals_bitmap, lra_reg_info[regno].val)) + { + lra_set_regno_unique_value (regno); + if (lra_dump_file != NULL) + fprintf (lra_dump_file, + " Make unique value for inheritance r%d\n", regno); + } + bitmap_clear (&result_pseudo_vals_bitmap); bitmap_clear (&used_pseudos_bitmap); bitmap_clear (&involved_insns_bitmap); bitmap_clear (&coalesced_pseudos_bitmap); diff -Naur gcc-4.8.2.orig/gcc/mode-switching.c gcc-4.8.2/gcc/mode-switching.c --- gcc-4.8.2.orig/gcc/mode-switching.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/mode-switching.c 2014-03-30 20:21:40.694263438 +0000 @@ -568,12 +568,15 @@ info[bb->index].computing = last_mode; /* Check for blocks without ANY mode requirements. - N.B. because of MODE_AFTER, last_mode might still be different - from no_mode. */ + N.B. because of MODE_AFTER, last_mode might still + be different from no_mode, in which case we need to + mark the block as nontransparent. */ if (!any_set_required) { ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now); add_seginfo (info + bb->index, ptr); + if (last_mode != no_mode) + bitmap_clear_bit (transp[bb->index], j); } } #if defined (MODE_ENTRY) && defined (MODE_EXIT) diff -Naur gcc-4.8.2.orig/gcc/optabs.c gcc-4.8.2/gcc/optabs.c --- gcc-4.8.2.orig/gcc/optabs.c 2013-03-09 07:54:02.000000000 +0000 +++ gcc-4.8.2/gcc/optabs.c 2014-03-30 20:21:40.694263438 +0000 @@ -4558,8 +4558,11 @@ if (!COMPARISON_P (comparison)) return NULL_RTX; - do_pending_stack_adjust (); + /* State variables we need to save and restore if cmove can't be used. */ + int save_pending_stack_adjust = pending_stack_adjust; + int save_stack_pointer_delta = stack_pointer_delta; last = get_last_insn (); + do_pending_stack_adjust (); prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1), GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN, &comparison, &cmode); @@ -4579,6 +4582,8 @@ } } delete_insns_since (last); + pending_stack_adjust = save_pending_stack_adjust; + stack_pointer_delta = save_stack_pointer_delta; return NULL_RTX; } @@ -6233,7 +6238,7 @@ /* If the optabs changed, record it. */ if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs))) - TREE_OPTIMIZATION_OPTABS (optnode) = (unsigned char *) tmp_optabs; + TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs; else { TREE_OPTIMIZATION_OPTABS (optnode) = NULL; @@ -7035,8 +7040,7 @@ create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); - /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[2], val, mode, true); + create_input_operand (&ops[2], val, mode); create_integer_operand (&ops[3], model); if (maybe_expand_insn (icode, 4, ops)) return ops[0].value; @@ -7075,8 +7079,7 @@ struct expand_operand ops[3]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); - /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[2], val, mode, true); + create_input_operand (&ops[2], val, mode); if (maybe_expand_insn (icode, 3, ops)) return ops[0].value; } @@ -7118,8 +7121,6 @@ { if (!target || !register_operand (target, mode)) target = gen_reg_rtx (mode); - if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode) - val = convert_modes (mode, GET_MODE (val), val, 1); if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX)) return target; } @@ -7331,8 +7332,8 @@ create_output_operand (&ops[0], target_bool, bool_mode); create_output_operand (&ops[1], target_oval, mode); create_fixed_operand (&ops[2], mem); - create_convert_operand_to (&ops[3], expected, mode, true); - create_convert_operand_to (&ops[4], desired, mode, true); + create_input_operand (&ops[3], expected, mode); + create_input_operand (&ops[4], desired, mode); create_integer_operand (&ops[5], is_weak); create_integer_operand (&ops[6], succ_model); create_integer_operand (&ops[7], fail_model); @@ -7353,8 +7354,8 @@ create_output_operand (&ops[0], target_oval, mode); create_fixed_operand (&ops[1], mem); - create_convert_operand_to (&ops[2], expected, mode, true); - create_convert_operand_to (&ops[3], desired, mode, true); + create_input_operand (&ops[2], expected, mode); + create_input_operand (&ops[3], desired, mode); if (!maybe_expand_insn (icode, 4, ops)) return false; diff -Naur gcc-4.8.2.orig/gcc/params.def gcc-4.8.2/gcc/params.def --- gcc-4.8.2.orig/gcc/params.def 2013-04-11 16:22:38.000000000 +0000 +++ gcc-4.8.2/gcc/params.def 2014-03-30 20:21:40.694263438 +0000 @@ -1014,6 +1014,12 @@ "strength reduction", 50, 1, 999999) +DEFPARAM (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS, + "uninit-control-dep-attempts", + "Maximum number of nested calls to search for control dependencies " + "during uninitialized variable analysis", + 1000, 1, 0) + /* Local variables: mode:c diff -Naur gcc-4.8.2.orig/gcc/passes.c gcc-4.8.2/gcc/passes.c --- gcc-4.8.2.orig/gcc/passes.c 2013-09-11 12:23:15.000000000 +0000 +++ gcc-4.8.2/gcc/passes.c 2014-03-30 20:21:40.694263438 +0000 @@ -1398,6 +1398,7 @@ /* After CCP we rewrite no longer addressed locals into SSA form if possible. */ NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_object_sizes); /* pass_build_alias is a dummy pass that ensures that we execute TODO_rebuild_alias at this point. */ NEXT_PASS (pass_build_alias); @@ -1435,7 +1436,6 @@ NEXT_PASS (pass_dce); NEXT_PASS (pass_forwprop); NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_object_sizes); NEXT_PASS (pass_strlen); NEXT_PASS (pass_ccp); /* After CCP we rewrite no longer addressed locals into SSA diff -Naur gcc-4.8.2.orig/gcc/print-rtl.c gcc-4.8.2/gcc/print-rtl.c --- gcc-4.8.2.orig/gcc/print-rtl.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/print-rtl.c 2014-03-30 20:21:40.694263438 +0000 @@ -582,6 +582,8 @@ if (MEM_EXPR (in_rtx)) print_mem_expr (outfile, MEM_EXPR (in_rtx)); + else + fputc (' ', outfile); if (MEM_OFFSET_KNOWN_P (in_rtx)) fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx)); diff -Naur gcc-4.8.2.orig/gcc/recog.c gcc-4.8.2/gcc/recog.c --- gcc-4.8.2.orig/gcc/recog.c 2013-08-05 20:24:39.000000000 +0000 +++ gcc-4.8.2/gcc/recog.c 2014-03-30 20:21:40.694263438 +0000 @@ -3061,6 +3061,9 @@ return 1; } +/* Regno offset to be used in the register search. */ +static int search_ofs; + /* Try to find a hard register of mode MODE, matching the register class in CLASS_STR, which is available at the beginning of insn CURRENT_INSN and remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX, @@ -3076,7 +3079,6 @@ peep2_find_free_register (int from, int to, const char *class_str, enum machine_mode mode, HARD_REG_SET *reg_set) { - static int search_ofs; enum reg_class cl; HARD_REG_SET live; df_ref *def_rec; @@ -3541,6 +3543,7 @@ /* Initialize the regsets we're going to use. */ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) peep2_insn_data[i].live_before = BITMAP_ALLOC (®_obstack); + search_ofs = 0; live = BITMAP_ALLOC (®_obstack); FOR_EACH_BB_REVERSE (bb) diff -Naur gcc-4.8.2.orig/gcc/regcprop.c gcc-4.8.2/gcc/regcprop.c --- gcc-4.8.2.orig/gcc/regcprop.c 2013-04-25 21:50:26.000000000 +0000 +++ gcc-4.8.2/gcc/regcprop.c 2014-03-30 20:21:40.697596881 +0000 @@ -747,6 +747,7 @@ int n_ops, i, alt, predicated; bool is_asm, any_replacements; rtx set; + rtx link; bool replaced[MAX_RECOG_OPERANDS]; bool changed = false; struct kill_set_value_data ksvd; @@ -815,6 +816,23 @@ if (recog_op_alt[i][alt].earlyclobber) kill_value (recog_data.operand[i], vd); + /* If we have dead sets in the insn, then we need to note these as we + would clobbers. */ + for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) + { + if (REG_NOTE_KIND (link) == REG_UNUSED) + { + kill_value (XEXP (link, 0), vd); + /* Furthermore, if the insn looked like a single-set, + but the dead store kills the source value of that + set, then we can no-longer use the plain move + special case below. */ + if (set + && reg_overlap_mentioned_p (XEXP (link, 0), SET_SRC (set))) + set = NULL; + } + } + /* Special-case plain move instructions, since we may well be able to do the move from a different register class. */ if (set && REG_P (SET_SRC (set))) diff -Naur gcc-4.8.2.orig/gcc/reginfo.c gcc-4.8.2/gcc/reginfo.c --- gcc-4.8.2.orig/gcc/reginfo.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/reginfo.c 2014-03-30 20:21:40.697596881 +0000 @@ -85,7 +85,7 @@ char global_regs[FIRST_PSEUDO_REGISTER]; /* Declaration for the global register. */ -static tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER]; +tree global_regs_decl[FIRST_PSEUDO_REGISTER]; /* Same information as REGS_INVALIDATED_BY_CALL but in regset form to be used in dataflow more conveniently. */ @@ -620,40 +620,35 @@ mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; - if (found_mode != VOIDmode) - return found_mode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; - if (found_mode != VOIDmode) - return found_mode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; - if (found_mode != VOIDmode) - return found_mode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; if (found_mode != VOIDmode) diff -Naur gcc-4.8.2.orig/gcc/reorg.c gcc-4.8.2/gcc/reorg.c --- gcc-4.8.2.orig/gcc/reorg.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/reorg.c 2014-03-30 20:21:40.697596881 +0000 @@ -1105,6 +1105,7 @@ int used_annul = 0; int i; struct resources cc_set; + bool *redundant; /* We can't do anything if there are more delay slots in SEQ than we can handle, or if we don't know that it will be a taken branch. @@ -1145,6 +1146,7 @@ return delay_list; #endif + redundant = XALLOCAVEC (bool, XVECLEN (seq, 0)); for (i = 1; i < XVECLEN (seq, 0); i++) { rtx trial = XVECEXP (seq, 0, i); @@ -1166,7 +1168,8 @@ /* If this insn was already done (usually in a previous delay slot), pretend we put it in our delay slot. */ - if (redundant_insn (trial, insn, new_delay_list)) + redundant[i] = redundant_insn (trial, insn, new_delay_list); + if (redundant[i]) continue; /* We will end up re-vectoring this branch, so compute flags @@ -1199,6 +1202,12 @@ return delay_list; } + /* Record the effect of the instructions that were redundant and which + we therefore decided not to copy. */ + for (i = 1; i < XVECLEN (seq, 0); i++) + if (redundant[i]) + update_block (XVECEXP (seq, 0, i), insn); + /* Show the place to which we will be branching. */ *pnew_thread = first_active_target_insn (JUMP_LABEL (XVECEXP (seq, 0, 0))); @@ -1262,6 +1271,7 @@ /* If this insn was already done, we don't need it. */ if (redundant_insn (trial, insn, delay_list)) { + update_block (trial, insn); delete_from_delay_slot (trial); continue; } @@ -3266,6 +3276,7 @@ to reprocess this insn. */ if (redundant_insn (XVECEXP (pat, 0, 1), delay_insn, 0)) { + update_block (XVECEXP (pat, 0, 1), insn); delete_from_delay_slot (XVECEXP (pat, 0, 1)); next = prev_active_insn (next); continue; @@ -3385,6 +3396,7 @@ && redirect_with_delay_slots_safe_p (delay_insn, target_label, insn)) { + update_block (XVECEXP (PATTERN (trial), 0, 1), insn); reorg_redirect_jump (delay_insn, target_label); next = insn; continue; diff -Naur gcc-4.8.2.orig/gcc/rtl.h gcc-4.8.2/gcc/rtl.h --- gcc-4.8.2.orig/gcc/rtl.h 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/rtl.h 2014-03-30 20:21:40.697596881 +0000 @@ -2705,6 +2705,8 @@ const_rtx, rtx); extern int read_dependence (const_rtx, const_rtx); extern int anti_dependence (const_rtx, const_rtx); +extern int canon_anti_dependence (const_rtx, bool, + const_rtx, enum machine_mode, rtx); extern int output_dependence (const_rtx, const_rtx); extern int may_alias_p (const_rtx, const_rtx); extern void init_alias_target (void); @@ -2789,6 +2791,8 @@ #define fatal_insn_not_found(insn) \ _fatal_insn_not_found (insn, __FILE__, __LINE__, __FUNCTION__) +/* reginfo.c */ +extern tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER]; #endif /* ! GCC_RTL_H */ diff -Naur gcc-4.8.2.orig/gcc/rtlanal.c gcc-4.8.2/gcc/rtlanal.c --- gcc-4.8.2.orig/gcc/rtlanal.c 2013-01-10 20:38:27.000000000 +0000 +++ gcc-4.8.2/gcc/rtlanal.c 2014-03-30 20:21:40.697596881 +0000 @@ -224,10 +224,10 @@ return 0; } -/* Return nonzero if the use of X as an address in a MEM can cause a trap. - MODE is the mode of the MEM (not that of X) and UNALIGNED_MEMS controls - whether nonzero is returned for unaligned memory accesses on strict - alignment machines. */ +/* Return nonzero if the use of X+OFFSET as an address in a MEM with SIZE + bytes can cause a trap. MODE is the mode of the MEM (not that of X) and + UNALIGNED_MEMS controls whether nonzero is returned for unaligned memory + references on strict alignment machines. */ static int rtx_addr_can_trap_p_1 (const_rtx x, HOST_WIDE_INT offset, HOST_WIDE_INT size, @@ -235,11 +235,12 @@ { enum rtx_code code = GET_CODE (x); - if (STRICT_ALIGNMENT - && unaligned_mems - && GET_MODE_SIZE (mode) != 0) + /* The offset must be a multiple of the mode size if we are considering + unaligned memory references on strict alignment machines. */ + if (STRICT_ALIGNMENT && unaligned_mems && GET_MODE_SIZE (mode) != 0) { HOST_WIDE_INT actual_offset = offset; + #ifdef SPARC_STACK_BOUNDARY_HACK /* ??? The SPARC port may claim a STACK_BOUNDARY higher than the real alignment of %sp. However, when it does this, the @@ -298,8 +299,27 @@ return 0; case REG: - /* As in rtx_varies_p, we have to use the actual rtx, not reg number. */ - if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx + /* Stack references are assumed not to trap, but we need to deal with + nonsensical offsets. */ + if (x == frame_pointer_rtx) + { + HOST_WIDE_INT adj_offset = offset - STARTING_FRAME_OFFSET; + if (size == 0) + size = GET_MODE_SIZE (mode); + if (FRAME_GROWS_DOWNWARD) + { + if (adj_offset < frame_offset || adj_offset + size - 1 >= 0) + return 1; + } + else + { + if (adj_offset < 0 || adj_offset + size - 1 >= frame_offset) + return 1; + } + return 0; + } + /* ??? Need to add a similar guard for nonsensical offsets. */ + if (x == hard_frame_pointer_rtx || x == stack_pointer_rtx /* The arg pointer varies if it is not a fixed register. */ || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])) @@ -320,9 +340,7 @@ if (XEXP (x, 0) == pic_offset_table_rtx && CONSTANT_P (XEXP (x, 1))) return 0; - /* - or it is an address that can't trap plus a constant integer, - with the proper remainder modulo the mode size if we are - considering unaligned memory references. */ + /* - or it is an address that can't trap plus a constant integer. */ if (CONST_INT_P (XEXP (x, 1)) && !rtx_addr_can_trap_p_1 (XEXP (x, 0), offset + INTVAL (XEXP (x, 1)), size, mode, unaligned_mems)) diff -Naur gcc-4.8.2.orig/gcc/sdbout.c gcc-4.8.2/gcc/sdbout.c --- gcc-4.8.2.orig/gcc/sdbout.c 2013-03-05 17:59:38.000000000 +0000 +++ gcc-4.8.2/gcc/sdbout.c 2014-03-30 20:21:40.697596881 +0000 @@ -1226,7 +1226,10 @@ sdbout_parms (tree parms) { for (; parms; parms = TREE_CHAIN (parms)) - if (DECL_NAME (parms)) + if (DECL_NAME (parms) + && TREE_TYPE (parms) != error_mark_node + && DECL_RTL_SET_P (parms) + && DECL_INCOMING_RTL (parms)) { int current_sym_value = 0; const char *name = IDENTIFIER_POINTER (DECL_NAME (parms)); @@ -1358,7 +1361,10 @@ sdbout_reg_parms (tree parms) { for (; parms; parms = TREE_CHAIN (parms)) - if (DECL_NAME (parms)) + if (DECL_NAME (parms) + && TREE_TYPE (parms) != error_mark_node + && DECL_RTL_SET_P (parms) + && DECL_INCOMING_RTL (parms)) { const char *name = IDENTIFIER_POINTER (DECL_NAME (parms)); diff -Naur gcc-4.8.2.orig/gcc/sel-sched.c gcc-4.8.2/gcc/sel-sched.c --- gcc-4.8.2.orig/gcc/sel-sched.c 2013-02-19 13:50:50.000000000 +0000 +++ gcc-4.8.2/gcc/sel-sched.c 2014-03-30 20:21:40.697596881 +0000 @@ -1253,7 +1253,7 @@ if (!HARD_FRAME_POINTER_IS_FRAME_POINTER) add_to_hard_reg_set (®_rename_p->unavailable_hard_regs, - Pmode, HARD_FRAME_POINTER_IS_FRAME_POINTER); + Pmode, HARD_FRAME_POINTER_REGNUM); } #ifdef STACK_REGS diff -Naur gcc-4.8.2.orig/gcc/simplify-rtx.c gcc-4.8.2/gcc/simplify-rtx.c --- gcc-4.8.2.orig/gcc/simplify-rtx.c 2013-07-08 08:15:01.000000000 +0000 +++ gcc-4.8.2/gcc/simplify-rtx.c 2014-03-30 20:21:40.700930325 +0000 @@ -639,11 +639,16 @@ XEXP (op, 0), origmode); } - /* Simplify (truncate:SI (op:DI (x:DI) (y:DI))) - to (op:SI (truncate:SI (x:DI)) (truncate:SI (x:DI))). */ - if (GET_CODE (op) == PLUS - || GET_CODE (op) == MINUS - || GET_CODE (op) == MULT) + /* If the machine can perform operations in the truncated mode, distribute + the truncation, i.e. simplify (truncate:QI (op:SI (x:SI) (y:SI))) into + (op:QI (truncate:QI (x:SI)) (truncate:QI (y:SI))). */ + if (1 +#ifdef WORD_REGISTER_OPERATIONS + && precision >= BITS_PER_WORD +#endif + && (GET_CODE (op) == PLUS + || GET_CODE (op) == MINUS + || GET_CODE (op) == MULT)) { rtx op0 = simplify_gen_unary (TRUNCATE, mode, XEXP (op, 0), op_mode); if (op0) diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/convert-vec-1.c gcc-4.8.2/gcc/testsuite/c-c++-common/convert-vec-1.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/convert-vec-1.c 2012-10-09 06:18:29.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/convert-vec-1.c 2014-03-30 20:21:40.700930325 +0000 @@ -1,3 +1,4 @@ /* { dg-do compile } */ +/* { dg-prune-output "changes the ABI" } */ typedef float v2sf __attribute__ ((vector_size (8))); v2sf sub (void) { return (v2sf) 0.0; } /* { dg-error "can't convert" } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr58844-1.c gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr58844-1.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr58844-1.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr58844-1.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,8 @@ +/* PR preprocessor/58844 */ +/* { dg-do compile } */ +/* { dg-options "-ftrack-macro-expansion=0" } */ + +#define A x######x +int A = 1; +#define A x######x /* { dg-message "previous definition" } */ +#define A x##x /* { dg-warning "redefined" } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr58844-2.c gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr58844-2.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr58844-2.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr58844-2.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,8 @@ +/* PR preprocessor/58844 */ +/* { dg-do compile } */ +/* { dg-options "-ftrack-macro-expansion=2" } */ + +#define A x######x +int A = 1; +#define A x######x /* { dg-message "previous definition" } */ +#define A x##x /* { dg-warning "redefined" } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr60400-1.h gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr60400-1.h --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr60400-1.h 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr60400-1.h 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,3 @@ +??=ifndef PR60400_1_H +??=define PR60400_1_H +??=endif diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr60400-2.h gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr60400-2.h --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr60400-2.h 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr60400-2.h 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,4 @@ +??=ifndef PR60400_2_H +??=define PR60400_2_H +??=include "pr60400-1.h" +??=endif diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr60400.c gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr60400.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/cpp/pr60400.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/cpp/pr60400.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,13 @@ +/* PR preprocessor/60400 */ +/* { dg-do compile } */ +/* { dg-options "-trigraphs -Wtrigraphs" } */ + +??=include "pr60400-1.h" +??=include "pr60400-2.h" + +/* { dg-warning "trigraph" "" { target *-*-* } 1 } */ +/* { dg-warning "trigraph" "" { target *-*-* } 2 } */ +/* { dg-warning "trigraph" "" { target *-*-* } 3 } */ +/* { dg-warning "trigraph" "" { target *-*-* } 4 } */ +/* { dg-warning "trigraph" "" { target *-*-* } 5 } */ +/* { dg-warning "trigraph" "" { target *-*-* } 6 } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/fold-divmul-1.c gcc-4.8.2/gcc/testsuite/c-c++-common/fold-divmul-1.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/fold-divmul-1.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/fold-divmul-1.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original" } */ + +int * +fx (int *b, int *e) +{ + return b + (e - b); +} + +/* { dg-final { scan-tree-dump-not "/\\\[ex\\\]" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/gomp/pr58809.c gcc-4.8.2/gcc/testsuite/c-c++-common/gomp/pr58809.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/gomp/pr58809.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/gomp/pr58809.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,31 @@ +/* PR middle-end/58809 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +_Complex int j; +_Complex double d; + +void +foo (void) +{ + #pragma omp parallel reduction (&:j) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (|:j) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (^:j) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (min:j) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (max:j) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (&:d) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (|:d) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (^:d) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (min:d) /* { dg-error "has invalid type for" } */ + ; + #pragma omp parallel reduction (max:d) /* { dg-error "has invalid type for" } */ + ; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/gomp/pr59467.c gcc-4.8.2/gcc/testsuite/c-c++-common/gomp/pr59467.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/gomp/pr59467.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/gomp/pr59467.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,68 @@ +/* PR libgomp/59467 */ + +int v; + +void +foo (void) +{ + int x = 0, y = 0; + #pragma omp parallel + { + int z; + #pragma omp single copyprivate (x) /* { dg-error "is not threadprivate or private in outer context" } */ + { + #pragma omp atomic write + x = 6; + } + #pragma omp atomic read + z = x; + #pragma omp atomic + y += z; + } + #pragma omp parallel + { + int z; + #pragma omp single copyprivate (v) /* { dg-error "is not threadprivate or private in outer context" } */ + { + #pragma omp atomic write + v = 6; + } + #pragma omp atomic read + z = v; + #pragma omp atomic + y += z; + } + #pragma omp parallel private (x) + { + int z; + #pragma omp single copyprivate (x) + { + #pragma omp atomic write + x = 6; + } + #pragma omp atomic read + z = x; + #pragma omp atomic + y += z; + } + x = 0; + #pragma omp parallel reduction (+:x) + { + #pragma omp single copyprivate (x) + { + #pragma omp atomic write + x = 6; + } + #pragma omp atomic + y += x; + } + #pragma omp single copyprivate (x) + { + x = 7; + } + #pragma omp single copyprivate (v) /* { dg-error "is not threadprivate or private in outer context" } */ + { + #pragma omp atomic write + v = 6; + } +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr37743.c gcc-4.8.2/gcc/testsuite/c-c++-common/pr37743.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr37743.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/pr37743.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,13 @@ +/* PR c/37743 */ +/* This needs to be run only on targets where __UINT32_TYPE__ is defined + to unsigned int. */ +/* { dg-do compile { target *-*-linux-gnu* } } */ +/* { dg-options "-Wformat" } */ + +int foo (const char *, ...) __attribute__ ((format (printf, 1, 2))); + +void +bar (unsigned int x) +{ + foo ("%x", __builtin_bswap32 (x)); +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr59032.c gcc-4.8.2/gcc/testsuite/c-c++-common/pr59032.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr59032.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/pr59032.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void +foo() +{ + float v __attribute__((vector_size(8))); + v++; +} + +void +foo2 () +{ + float v __attribute__((vector_size(8))); + ++v; +} + +void +foo3 () +{ + float v __attribute__((vector_size(8))); + v--; +} + +void +foo4 () +{ + float v __attribute__((vector_size(8))); + --v; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr59037.c gcc-4.8.2/gcc/testsuite/c-c++-common/pr59037.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr59037.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/pr59037.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef int v4si __attribute__ ((vector_size (16))); + +int +main (int argc, char** argv) +{ + v4si x = {0,1,2,3}; + x = (v4si) {(x)[3], (x)[2], (x)[1], (x)[0]}; + return x[4]; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr59280.c gcc-4.8.2/gcc/testsuite/c-c++-common/pr59280.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr59280.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/pr59280.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,4 @@ +/* PR c/59280 */ +/* { dg-do compile } */ + +void bar (char *) __attribute__((constructor(foo))); /* { dg-error "constructor priorities must be integers|was not declared|constructor priorities are not supported" } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr60101.c gcc-4.8.2/gcc/testsuite/c-c++-common/pr60101.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/pr60101.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/pr60101.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,112 @@ +/* PR c/60101 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall" } */ + +extern int *a, b, *c, *d; + +void +foo (double _Complex *x, double _Complex *y, double _Complex *z, unsigned int l, int w) +{ + unsigned int e = (unsigned int) a[3]; + double _Complex (*v)[l][4][e][l][4] = (double _Complex (*)[l][4][e][l][4]) z; + double _Complex (*f)[l][b][l] = (double _Complex (*)[l][b][l]) y; + unsigned int g = c[0] * c[1] * c[2]; + unsigned int h = d[0] + c[0] * (d[1] + c[1] * d[2]); + unsigned int i; + + for (i = 0; i < e; i++) + { + int j = e * d[3] + i; + + unsigned int n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11; + float _Complex s = 0.; + unsigned int t = 0; + + for (n0 = 0; n0 < l; n0++) + for (n1 = 0; n1 < l; n1++) + for (n2 = 0; n2 < l; n2++) + for (n3 = 0; n3 < l; n3++) + for (n4 = 0; n4 < l; n4++) + for (n5 = 0; n5 < l; n5++) + for (n6 = 0; n6 < l; n6++) + for (n7 = 0; n7 < l; n7++) + for (n8 = 0; n8 < l; n8++) + for (n9 = 0; n9 < l; n9++) + for (n10 = 0; n10 < l; n10++) + for (n11 = 0; n11 < l; n11++) + { + if (t % g == h) + s + += f[n0][n4][j][n8] * f[n1][n5][j][n9] * ~(f[n2][n6][w][n10]) * ~(f[n3][n7][w][n11]) + * (+0.25 * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n10][0][i][n4][1] + * v[0][n7][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 0.25 * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n10][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n7][1][i][n0][0] + - 0.5 * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n10][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 0.25 * v[0][n2][0][i][n9][1] * v[0][n10][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n7][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n11][1][i][n0][0] + - 0.5 * v[0][n2][0][i][n9][1] * v[0][n10][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n7][1][i][n0][0] + + 0.25 * v[0][n2][0][i][n9][1] * v[0][n10][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 0.25 * v[0][n3][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n10][0][i][n4][1] + * v[0][n6][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n7][1][i][n0][0] + - 0.5 * v[0][n3][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n10][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n7][1][i][n0][0] + + 0.25 * v[0][n3][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n10][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 0.25 * v[0][n3][0][i][n9][1] * v[0][n10][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n6][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n11][1][i][n0][0] + + 0.25 * v[0][n3][0][i][n9][1] * v[0][n10][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n7][1][i][n0][0] + - 0.5 * v[0][n3][0][i][n9][1] * v[0][n10][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 0.25 * v[0][n10][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n6][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n11][1][i][n0][0] + - 0.5 * v[0][n10][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n6][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n7][1][i][n0][0] + - 0.5 * v[0][n10][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n7][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n11][1][i][n0][0] + + 0.25 * v[0][n10][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n7][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 1. * v[0][n10][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n7][1][i][n0][0] + - 0.5 * v[0][n10][0][i][n9][1] * v[0][n2][0][i][n5][1] * v[0][n3][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n6][1][i][n0][0] + - 0.5 * v[0][n10][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n6][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n11][1][i][n0][0] + + 0.25 * v[0][n10][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n6][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n7][1][i][n0][0] + + 0.25 * v[0][n10][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n7][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n11][1][i][n0][0] + - 0.5 * v[0][n10][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n7][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n6][1][i][n0][0] + - 0.5 * v[0][n10][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n6][1][i][n1][0] * v[0][n7][1][i][n0][0] + + 1. * v[0][n10][0][i][n9][1] * v[0][n3][0][i][n5][1] * v[0][n2][0][i][n4][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n6][1][i][n0][0] + + 0.5 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] + * v[0][n7][1][i][n1][0] * v[0][n11][1][i][n0][0] * v[0][n10][0][i][n8][0] + - 0.25 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] + * v[0][n11][1][i][n1][0] * v[0][n7][1][i][n0][0] * v[0][n10][0][i][n8][0] + - 0.25 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] + * v[0][n7][1][i][n8][0] * v[0][n11][1][i][n0][0] * v[0][n10][0][i][n1][0] + + 0.25 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] + * v[0][n7][1][i][n8][0] * v[0][n11][1][i][n1][0] * v[0][n10][0][i][n0][0] + + 0.25 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n0][0] * v[0][n10][0][i][n1][0] + - 0.5 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n3][0][i][n5][1] + * v[0][n11][1][i][n8][0] * v[0][n7][1][i][n1][0] * v[0][n10][0][i][n0][0] + - 0.25 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n10][0][i][n5][1] + * v[0][n7][1][i][n1][0] * v[0][n11][1][i][n0][0] * v[0][n3][0][i][n8][0] + - 0.25 * v[0][n6][1][i][n4][1] * v[0][n2][0][i][n9][1] * v[0][n10][0][i][n5][1] + * v[0][n7][1][i][n8][0] * v[0][n11][1][i][n0][0] * v[0][n3][0][i][n1][0]); + t++; + } + int u = (j - w + b) % b; + int q = (j >= w ? +1 : -1); + int r = q; + x[u] += r * s; + } +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/scal-to-vec2.c gcc-4.8.2/gcc/testsuite/c-c++-common/scal-to-vec2.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/scal-to-vec2.c 2012-11-10 14:26:54.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/scal-to-vec2.c 2014-03-30 20:21:40.700930325 +0000 @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-fno-common" { target hppa*-*-hpux* } } */ /* { dg-options "-mabi=altivec" { target { { powerpc*-*-linux* } && ilp32 } } } */ +/* { dg-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ /* Ignore warning on some powerpc-ibm-aix configurations. */ /* { dg-prune-output "non-standard ABI extension" } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/torture/pr58794-1.c gcc-4.8.2/gcc/testsuite/c-c++-common/torture/pr58794-1.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/torture/pr58794-1.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/torture/pr58794-1.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,29 @@ +/* { dg-do compile } */ + +struct S0 +{ + int f; +}; + +struct S1 +{ + struct S0 f1; + volatile int f2; +}; + +struct S2 +{ + struct S1 g; +} a, b; + +static int *c[1][2] = {{0, (int *)&a.g.f2}}; +static int d; + +int +main () +{ + for (d = 0; d < 1; d++) + for (b.g.f1.f = 0; b.g.f1.f < 1; b.g.f1.f++) + *c[b.g.f1.f][d + 1] = 0; + return 0; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/torture/pr58794-2.c gcc-4.8.2/gcc/testsuite/c-c++-common/torture/pr58794-2.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/torture/pr58794-2.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/torture/pr58794-2.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +struct S +{ + volatile int f; +} a; + +unsigned int b; + +static int *c[1][2] = {{0, (int *)&a.f}}; +static unsigned int d; + +int +main () +{ + for (; d < 1; d++) + for (; b < 1; b++) + *c[b][d + 1] = 0; + + return 0; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/torture/pr60026.c gcc-4.8.2/gcc/testsuite/c-c++-common/torture/pr60026.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/torture/pr60026.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/torture/pr60026.c 2014-03-30 20:21:40.700930325 +0000 @@ -0,0 +1,28 @@ +/* PR ipa/60026 */ +/* { dg-do compile } */ + +struct S { int f; } a; + +__attribute__((optimize (0))) +struct S foo (int x, struct S y) +{ + int b = y.f; + return a; +} + +void +bar () +{ + while (a.f) + { + struct S c = {0}; + foo (0, c); + } +} + +int +main () +{ + bar (); + return 0; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/c-c++-common/vector-compare-2.c gcc-4.8.2/gcc/testsuite/c-c++-common/vector-compare-2.c --- gcc-4.8.2.orig/gcc/testsuite/c-c++-common/vector-compare-2.c 2012-11-10 14:26:54.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/c-c++-common/vector-compare-2.c 2014-03-30 20:21:40.700930325 +0000 @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-fno-common" { target hppa*-*-hpux* } } */ /* { dg-options "-mabi=altivec" { target { { powerpc*-*-linux* } && ilp32 } } } */ +/* { dg-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ /* Ignore warning on some powerpc-ibm-aix configurations. */ /* { dg-prune-output "non-standard ABI extension" } */ diff -Naur gcc-4.8.2.orig/gcc/testsuite/g++.dg/conversion/simd1.C gcc-4.8.2/gcc/testsuite/g++.dg/conversion/simd1.C --- gcc-4.8.2.orig/gcc/testsuite/g++.dg/conversion/simd1.C 2010-12-08 21:37:51.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/g++.dg/conversion/simd1.C 2014-03-30 20:21:40.720930982 +0000 @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ /* Test overload resolution of vector types. From Janis Johnson and Paolo Bonzini, based on PR/16882 */ @@ -17,7 +18,7 @@ void foo () { vss = vld(i, vscp); /* { dg-error "no matching function for call" } */ - // { dg-message "candidate" "candidate note" { target *-*-* } 19 } + // { dg-message "candidate" "candidate note" { target *-*-* } 20 } vss = vld(i, vssp); vss = vld(i, cvssp); } diff -Naur gcc-4.8.2.orig/gcc/testsuite/g++.dg/cpp0x/access02.C gcc-4.8.2/gcc/testsuite/g++.dg/cpp0x/access02.C --- gcc-4.8.2.orig/gcc/testsuite/g++.dg/cpp0x/access02.C 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/g++.dg/cpp0x/access02.C 2014-03-30 20:21:40.720930982 +0000 @@ -0,0 +1,39 @@ +// PR c++/58954 +// { dg-require-effective-target c++11 } + +template +T&& declval(); + +template +struct foo_argument +{ + template + static Arg test(Ret (C::*)(Arg)); + + typedef decltype(test(&T::template foo<>)) type; +}; + +template +struct dependent { typedef T type; }; + +template +struct base +{ + template + auto foo(int i) -> decltype(declval< + typename dependent::type + >().foo_impl(i)); +}; + +struct derived : base +{ + friend struct base; +private: + int foo_impl(int i); +}; + +int main() +{ + foo_argument::type var = 0; + return var; +} diff -Naur gcc-4.8.2.orig/gcc/testsuite/g++.dg/cpp0x/alias-decl-41.C gcc-4.8.2/gcc/testsuite/g++.dg/cpp0x/alias-decl-41.C --- gcc-4.8.2.orig/gcc/testsuite/g++.dg/cpp0x/alias-decl-41.C 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.8.2/gcc/testsuite/g++.dg/cpp0x/alias-decl-41.C 2014-03-30 20:21:40.720930982 +0000 @@ -0,0 +1,18 @@ +// PR c++/60182 +// { dg-require-effective-target c++11 } + +class B {}; +template using __allocator_base = B; +template class F : __allocator_base {}; +class C {}; +template > class G : C {}; +template class D; +class A { + using Container = G>; + A(); + A(D const &); + Container m_elements; +}; +template