diff options
| author | Khem Raj <raj.khem@gmail.com> | 2012-03-06 17:21:34 +0000 |
|---|---|---|
| committer | Khem Raj <raj.khem@gmail.com> | 2012-03-08 18:57:24 -0800 |
| commit | f256ccfb85b8b14b9b72991d5be1d3ec02f828a8 (patch) | |
| tree | 543109c7ccfc9b40e76662d1fccef5e257ff360c | |
| parent | 8a728abad7307e968a03b333811fc1f816ba18b4 (diff) | |
| download | meta-openembedded-f256ccfb85b8b14b9b72991d5be1d3ec02f828a8.tar.gz | |
gcc-4.6: Adjust to match gcc 4.6.3 from OE-Core
Update linaro patches
Signed-off-by: Khem Raj <raj.khem@gmail.com>
18 files changed, 3197 insertions, 780 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/fix_linaro_106872.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/fix_linaro_106872.patch new file mode 100644 index 0000000000..ef33afff70 --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/fix_linaro_106872.patch | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | Index: gcc-4_6-branch/gcc/config/arm/arm.c | ||
| 2 | =================================================================== | ||
| 3 | --- gcc-4_6-branch.orig/gcc/config/arm/arm.c 2012-03-05 17:14:09.901129286 -0800 | ||
| 4 | +++ gcc-4_6-branch/gcc/config/arm/arm.c 2012-03-05 17:18:23.061141606 -0800 | ||
| 5 | @@ -17525,6 +17525,13 @@ | ||
| 6 | } | ||
| 7 | return; | ||
| 8 | |||
| 9 | + case 'v': | ||
| 10 | + { | ||
| 11 | + gcc_assert (GET_CODE (x) == CONST_DOUBLE); | ||
| 12 | + fprintf (stream, "#%d", vfp3_const_double_for_fract_bits (x)); | ||
| 13 | + return; | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | /* Register specifier for vld1.16/vst1.16. Translate the S register | ||
| 17 | number into a D register number and element index. */ | ||
| 18 | case 'z': | ||
| 19 | @@ -24925,4 +24932,26 @@ | ||
| 20 | return 4; | ||
| 21 | } | ||
| 22 | |||
| 23 | +int | ||
| 24 | +vfp3_const_double_for_fract_bits (rtx operand) | ||
| 25 | +{ | ||
| 26 | + REAL_VALUE_TYPE r0; | ||
| 27 | + | ||
| 28 | + if (GET_CODE (operand) != CONST_DOUBLE) | ||
| 29 | + return 0; | ||
| 30 | + | ||
| 31 | + REAL_VALUE_FROM_CONST_DOUBLE (r0, operand); | ||
| 32 | + if (exact_real_inverse (DFmode, &r0)) | ||
| 33 | + { | ||
| 34 | + if (exact_real_truncate (DFmode, &r0)) | ||
| 35 | + { | ||
| 36 | + HOST_WIDE_INT value = real_to_integer (&r0); | ||
| 37 | + value = value & 0xffffffff; | ||
| 38 | + if ((value != 0) && ( (value & (value - 1)) == 0)) | ||
| 39 | + return int_log2 (value); | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + return 0; | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | #include "gt-arm.h" | ||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106740.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106740.patch deleted file mode 100644 index 11a1da6709..0000000000 --- a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106740.patch +++ /dev/null | |||
| @@ -1,294 +0,0 @@ | |||
| 1 | 2011-05-04 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline: | ||
| 4 | |||
| 5 | 2011-03-29 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 6 | |||
| 7 | PR debug/48190 | ||
| 8 | * dwarf2out.c (dw_loc_list_node): Add resolved_addr and replaced. | ||
| 9 | (cached_dw_loc_list_def): New structure. | ||
| 10 | (cached_dw_loc_list): New typedef. | ||
| 11 | (cached_dw_loc_list_table): New variable. | ||
| 12 | (cached_dw_loc_list_table_hash): New function. | ||
| 13 | (cached_dw_loc_list_table_eq): Likewise. | ||
| 14 | (add_location_or_const_value_attribute): Take a bool cache_p. | ||
| 15 | Cache the list when the parameter is true. | ||
| 16 | (gen_formal_parameter_die): Update caller. | ||
| 17 | (gen_variable_die): Likewise. | ||
| 18 | (dwarf2out_finish): Likewise. | ||
| 19 | (dwarf2out_abstract_function): Nullify cached_dw_loc_list_table | ||
| 20 | while generating debug info for the decl. | ||
| 21 | (dwarf2out_function_decl): Clear cached_dw_loc_list_table. | ||
| 22 | (dwarf2out_init): Initialize cached_dw_loc_list_table. | ||
| 23 | (resolve_addr): Cache the result of resolving a chain of | ||
| 24 | location lists. | ||
| 25 | |||
| 26 | === modified file 'gcc/dwarf2out.c' | ||
| 27 | --- old/gcc/dwarf2out.c 2011-03-29 22:47:59 +0000 | ||
| 28 | +++ new/gcc/dwarf2out.c 2011-05-04 13:20:12 +0000 | ||
| 29 | @@ -4427,6 +4427,11 @@ | ||
| 30 | const char *section; /* Section this loclist is relative to */ | ||
| 31 | dw_loc_descr_ref expr; | ||
| 32 | hashval_t hash; | ||
| 33 | + /* True if all addresses in this and subsequent lists are known to be | ||
| 34 | + resolved. */ | ||
| 35 | + bool resolved_addr; | ||
| 36 | + /* True if this list has been replaced by dw_loc_next. */ | ||
| 37 | + bool replaced; | ||
| 38 | bool emitted; | ||
| 39 | } dw_loc_list_node; | ||
| 40 | |||
| 41 | @@ -6087,6 +6092,19 @@ | ||
| 42 | /* Table of decl location linked lists. */ | ||
| 43 | static GTY ((param_is (var_loc_list))) htab_t decl_loc_table; | ||
| 44 | |||
| 45 | +/* A cached location list. */ | ||
| 46 | +struct GTY (()) cached_dw_loc_list_def { | ||
| 47 | + /* The DECL_UID of the decl that this entry describes. */ | ||
| 48 | + unsigned int decl_id; | ||
| 49 | + | ||
| 50 | + /* The cached location list. */ | ||
| 51 | + dw_loc_list_ref loc_list; | ||
| 52 | +}; | ||
| 53 | +typedef struct cached_dw_loc_list_def cached_dw_loc_list; | ||
| 54 | + | ||
| 55 | +/* Table of cached location lists. */ | ||
| 56 | +static GTY ((param_is (cached_dw_loc_list))) htab_t cached_dw_loc_list_table; | ||
| 57 | + | ||
| 58 | /* A pointer to the base of a list of references to DIE's that | ||
| 59 | are uniquely identified by their tag, presence/absence of | ||
| 60 | children DIE's, and list of attribute/value pairs. */ | ||
| 61 | @@ -6434,7 +6452,7 @@ | ||
| 62 | static void insert_double (double_int, unsigned char *); | ||
| 63 | static void insert_float (const_rtx, unsigned char *); | ||
| 64 | static rtx rtl_for_decl_location (tree); | ||
| 65 | -static bool add_location_or_const_value_attribute (dw_die_ref, tree, | ||
| 66 | +static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool, | ||
| 67 | enum dwarf_attribute); | ||
| 68 | static bool tree_add_const_value_attribute (dw_die_ref, tree); | ||
| 69 | static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree); | ||
| 70 | @@ -8168,6 +8186,24 @@ | ||
| 71 | htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl)); | ||
| 72 | } | ||
| 73 | |||
| 74 | +/* Returns a hash value for X (which really is a cached_dw_loc_list_list). */ | ||
| 75 | + | ||
| 76 | +static hashval_t | ||
| 77 | +cached_dw_loc_list_table_hash (const void *x) | ||
| 78 | +{ | ||
| 79 | + return (hashval_t) ((const cached_dw_loc_list *) x)->decl_id; | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +/* Return nonzero if decl_id of cached_dw_loc_list X is the same as | ||
| 83 | + UID of decl *Y. */ | ||
| 84 | + | ||
| 85 | +static int | ||
| 86 | +cached_dw_loc_list_table_eq (const void *x, const void *y) | ||
| 87 | +{ | ||
| 88 | + return (((const cached_dw_loc_list *) x)->decl_id | ||
| 89 | + == DECL_UID ((const_tree) y)); | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | /* Equate a DIE to a particular declaration. */ | ||
| 93 | |||
| 94 | static void | ||
| 95 | @@ -16965,15 +17001,22 @@ | ||
| 96 | these things can crop up in other ways also.) Note that one type of | ||
| 97 | constant value which can be passed into an inlined function is a constant | ||
| 98 | pointer. This can happen for example if an actual argument in an inlined | ||
| 99 | - function call evaluates to a compile-time constant address. */ | ||
| 100 | + function call evaluates to a compile-time constant address. | ||
| 101 | + | ||
| 102 | + CACHE_P is true if it is worth caching the location list for DECL, | ||
| 103 | + so that future calls can reuse it rather than regenerate it from scratch. | ||
| 104 | + This is true for BLOCK_NONLOCALIZED_VARS in inlined subroutines, | ||
| 105 | + since we will need to refer to them each time the function is inlined. */ | ||
| 106 | |||
| 107 | static bool | ||
| 108 | -add_location_or_const_value_attribute (dw_die_ref die, tree decl, | ||
| 109 | +add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p, | ||
| 110 | enum dwarf_attribute attr) | ||
| 111 | { | ||
| 112 | rtx rtl; | ||
| 113 | dw_loc_list_ref list; | ||
| 114 | var_loc_list *loc_list; | ||
| 115 | + cached_dw_loc_list *cache; | ||
| 116 | + void **slot; | ||
| 117 | |||
| 118 | if (TREE_CODE (decl) == ERROR_MARK) | ||
| 119 | return false; | ||
| 120 | @@ -17010,7 +17053,33 @@ | ||
| 121 | && add_const_value_attribute (die, rtl)) | ||
| 122 | return true; | ||
| 123 | } | ||
| 124 | - list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2); | ||
| 125 | + /* If this decl is from BLOCK_NONLOCALIZED_VARS, we might need its | ||
| 126 | + list several times. See if we've already cached the contents. */ | ||
| 127 | + list = NULL; | ||
| 128 | + if (loc_list == NULL || cached_dw_loc_list_table == NULL) | ||
| 129 | + cache_p = false; | ||
| 130 | + if (cache_p) | ||
| 131 | + { | ||
| 132 | + cache = (cached_dw_loc_list *) | ||
| 133 | + htab_find_with_hash (cached_dw_loc_list_table, decl, DECL_UID (decl)); | ||
| 134 | + if (cache) | ||
| 135 | + list = cache->loc_list; | ||
| 136 | + } | ||
| 137 | + if (list == NULL) | ||
| 138 | + { | ||
| 139 | + list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2); | ||
| 140 | + /* It is usually worth caching this result if the decl is from | ||
| 141 | + BLOCK_NONLOCALIZED_VARS and if the list has at least two elements. */ | ||
| 142 | + if (cache_p && list && list->dw_loc_next) | ||
| 143 | + { | ||
| 144 | + slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl, | ||
| 145 | + DECL_UID (decl), INSERT); | ||
| 146 | + cache = ggc_alloc_cleared_cached_dw_loc_list (); | ||
| 147 | + cache->decl_id = DECL_UID (decl); | ||
| 148 | + cache->loc_list = list; | ||
| 149 | + *slot = cache; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | if (list) | ||
| 153 | { | ||
| 154 | add_AT_location_description (die, attr, list); | ||
| 155 | @@ -18702,7 +18771,7 @@ | ||
| 156 | equate_decl_number_to_die (node, parm_die); | ||
| 157 | if (! DECL_ABSTRACT (node_or_origin)) | ||
| 158 | add_location_or_const_value_attribute (parm_die, node_or_origin, | ||
| 159 | - DW_AT_location); | ||
| 160 | + node == NULL, DW_AT_location); | ||
| 161 | |||
| 162 | break; | ||
| 163 | |||
| 164 | @@ -18887,6 +18956,7 @@ | ||
| 165 | tree context; | ||
| 166 | int was_abstract; | ||
| 167 | htab_t old_decl_loc_table; | ||
| 168 | + htab_t old_cached_dw_loc_list_table; | ||
| 169 | |||
| 170 | /* Make sure we have the actual abstract inline, not a clone. */ | ||
| 171 | decl = DECL_ORIGIN (decl); | ||
| 172 | @@ -18901,6 +18971,8 @@ | ||
| 173 | get locations in abstract instantces. */ | ||
| 174 | old_decl_loc_table = decl_loc_table; | ||
| 175 | decl_loc_table = NULL; | ||
| 176 | + old_cached_dw_loc_list_table = cached_dw_loc_list_table; | ||
| 177 | + cached_dw_loc_list_table = NULL; | ||
| 178 | |||
| 179 | /* Be sure we've emitted the in-class declaration DIE (if any) first, so | ||
| 180 | we don't get confused by DECL_ABSTRACT. */ | ||
| 181 | @@ -18925,6 +18997,7 @@ | ||
| 182 | |||
| 183 | current_function_decl = save_fn; | ||
| 184 | decl_loc_table = old_decl_loc_table; | ||
| 185 | + cached_dw_loc_list_table = old_cached_dw_loc_list_table; | ||
| 186 | pop_cfun (); | ||
| 187 | } | ||
| 188 | |||
| 189 | @@ -19709,9 +19782,8 @@ | ||
| 190 | && !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin))) | ||
| 191 | defer_location (decl_or_origin, var_die); | ||
| 192 | else | ||
| 193 | - add_location_or_const_value_attribute (var_die, | ||
| 194 | - decl_or_origin, | ||
| 195 | - DW_AT_location); | ||
| 196 | + add_location_or_const_value_attribute (var_die, decl_or_origin, | ||
| 197 | + decl == NULL, DW_AT_location); | ||
| 198 | add_pubname (decl_or_origin, var_die); | ||
| 199 | } | ||
| 200 | else | ||
| 201 | @@ -21498,6 +21570,7 @@ | ||
| 202 | dwarf2out_decl (decl); | ||
| 203 | |||
| 204 | htab_empty (decl_loc_table); | ||
| 205 | + htab_empty (cached_dw_loc_list_table); | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Output a marker (i.e. a label) for the beginning of the generated code for | ||
| 209 | @@ -22230,6 +22303,11 @@ | ||
| 210 | decl_loc_table = htab_create_ggc (10, decl_loc_table_hash, | ||
| 211 | decl_loc_table_eq, NULL); | ||
| 212 | |||
| 213 | + /* Allocate the cached_dw_loc_list_table. */ | ||
| 214 | + cached_dw_loc_list_table | ||
| 215 | + = htab_create_ggc (10, cached_dw_loc_list_table_hash, | ||
| 216 | + cached_dw_loc_list_table_eq, NULL); | ||
| 217 | + | ||
| 218 | /* Allocate the initial hunk of the decl_scope_table. */ | ||
| 219 | decl_scope_table = VEC_alloc (tree, gc, 256); | ||
| 220 | |||
| 221 | @@ -22870,30 +22948,53 @@ | ||
| 222 | { | ||
| 223 | dw_die_ref c; | ||
| 224 | dw_attr_ref a; | ||
| 225 | - dw_loc_list_ref *curr; | ||
| 226 | + dw_loc_list_ref *curr, *start, loc; | ||
| 227 | unsigned ix; | ||
| 228 | |||
| 229 | FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a) | ||
| 230 | switch (AT_class (a)) | ||
| 231 | { | ||
| 232 | case dw_val_class_loc_list: | ||
| 233 | - curr = AT_loc_list_ptr (a); | ||
| 234 | - while (*curr) | ||
| 235 | + start = curr = AT_loc_list_ptr (a); | ||
| 236 | + loc = *curr; | ||
| 237 | + gcc_assert (loc); | ||
| 238 | + /* The same list can be referenced more than once. See if we have | ||
| 239 | + already recorded the result from a previous pass. */ | ||
| 240 | + if (loc->replaced) | ||
| 241 | + *curr = loc->dw_loc_next; | ||
| 242 | + else if (!loc->resolved_addr) | ||
| 243 | { | ||
| 244 | - if (!resolve_addr_in_expr ((*curr)->expr)) | ||
| 245 | + /* As things stand, we do not expect or allow one die to | ||
| 246 | + reference a suffix of another die's location list chain. | ||
| 247 | + References must be identical or completely separate. | ||
| 248 | + There is therefore no need to cache the result of this | ||
| 249 | + pass on any list other than the first; doing so | ||
| 250 | + would lead to unnecessary writes. */ | ||
| 251 | + while (*curr) | ||
| 252 | { | ||
| 253 | - dw_loc_list_ref next = (*curr)->dw_loc_next; | ||
| 254 | - if (next && (*curr)->ll_symbol) | ||
| 255 | + gcc_assert (!(*curr)->replaced && !(*curr)->resolved_addr); | ||
| 256 | + if (!resolve_addr_in_expr ((*curr)->expr)) | ||
| 257 | { | ||
| 258 | - gcc_assert (!next->ll_symbol); | ||
| 259 | - next->ll_symbol = (*curr)->ll_symbol; | ||
| 260 | + dw_loc_list_ref next = (*curr)->dw_loc_next; | ||
| 261 | + if (next && (*curr)->ll_symbol) | ||
| 262 | + { | ||
| 263 | + gcc_assert (!next->ll_symbol); | ||
| 264 | + next->ll_symbol = (*curr)->ll_symbol; | ||
| 265 | + } | ||
| 266 | + *curr = next; | ||
| 267 | } | ||
| 268 | - *curr = next; | ||
| 269 | + else | ||
| 270 | + curr = &(*curr)->dw_loc_next; | ||
| 271 | } | ||
| 272 | + if (loc == *start) | ||
| 273 | + loc->resolved_addr = 1; | ||
| 274 | else | ||
| 275 | - curr = &(*curr)->dw_loc_next; | ||
| 276 | + { | ||
| 277 | + loc->replaced = 1; | ||
| 278 | + loc->dw_loc_next = *start; | ||
| 279 | + } | ||
| 280 | } | ||
| 281 | - if (!AT_loc_list (a)) | ||
| 282 | + if (!*start) | ||
| 283 | { | ||
| 284 | remove_AT (die, a->dw_attr); | ||
| 285 | ix--; | ||
| 286 | @@ -23322,6 +23423,7 @@ | ||
| 287 | add_location_or_const_value_attribute ( | ||
| 288 | VEC_index (deferred_locations, deferred_locations_list, i)->die, | ||
| 289 | VEC_index (deferred_locations, deferred_locations_list, i)->variable, | ||
| 290 | + false, | ||
| 291 | DW_AT_location); | ||
| 292 | } | ||
| 293 | |||
| 294 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106741.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106741.patch index f53b26a888..6e76c21272 100644 --- a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106741.patch +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106741.patch | |||
| @@ -19,8 +19,8 @@ | |||
| 19 | === modified file 'gcc/combine.c' | 19 | === modified file 'gcc/combine.c' |
| 20 | Index: gcc-4_6-branch/gcc/combine.c | 20 | Index: gcc-4_6-branch/gcc/combine.c |
| 21 | =================================================================== | 21 | =================================================================== |
| 22 | --- gcc-4_6-branch.orig/gcc/combine.c 2011-09-16 19:58:21.000000000 -0700 | 22 | --- gcc-4_6-branch.orig/gcc/combine.c 2012-03-05 00:16:20.000000000 -0800 |
| 23 | +++ gcc-4_6-branch/gcc/combine.c 2011-09-16 20:05:36.626650681 -0700 | 23 | +++ gcc-4_6-branch/gcc/combine.c 2012-03-05 16:05:01.212928507 -0800 |
| 24 | @@ -391,8 +391,8 @@ | 24 | @@ -391,8 +391,8 @@ |
| 25 | static void undo_all (void); | 25 | static void undo_all (void); |
| 26 | static void undo_commit (void); | 26 | static void undo_commit (void); |
| @@ -32,7 +32,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 32 | static rtx simplify_if_then_else (rtx); | 32 | static rtx simplify_if_then_else (rtx); |
| 33 | static rtx simplify_set (rtx); | 33 | static rtx simplify_set (rtx); |
| 34 | static rtx simplify_logical (rtx); | 34 | static rtx simplify_logical (rtx); |
| 35 | @@ -3112,12 +3112,12 @@ | 35 | @@ -3119,12 +3119,12 @@ |
| 36 | if (i1) | 36 | if (i1) |
| 37 | { | 37 | { |
| 38 | subst_low_luid = DF_INSN_LUID (i1); | 38 | subst_low_luid = DF_INSN_LUID (i1); |
| @@ -47,7 +47,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | @@ -3129,7 +3129,7 @@ | 50 | @@ -3136,7 +3136,7 @@ |
| 51 | self-referential RTL when we will be substituting I1SRC for I1DEST | 51 | self-referential RTL when we will be substituting I1SRC for I1DEST |
| 52 | later. Likewise if I0 feeds into I2, either directly or indirectly | 52 | later. Likewise if I0 feeds into I2, either directly or indirectly |
| 53 | through I1, and I0DEST is in I0SRC. */ | 53 | through I1, and I0DEST is in I0SRC. */ |
| @@ -56,7 +56,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 56 | (i1_feeds_i2_n && i1dest_in_i1src) | 56 | (i1_feeds_i2_n && i1dest_in_i1src) |
| 57 | || ((i0_feeds_i2_n || (i0_feeds_i1_n && i1_feeds_i2_n)) | 57 | || ((i0_feeds_i2_n || (i0_feeds_i1_n && i1_feeds_i2_n)) |
| 58 | && i0dest_in_i0src)); | 58 | && i0dest_in_i0src)); |
| 59 | @@ -3168,7 +3168,7 @@ | 59 | @@ -3180,7 +3180,7 @@ |
| 60 | copy of I1SRC each time we substitute it, in order to avoid creating | 60 | copy of I1SRC each time we substitute it, in order to avoid creating |
| 61 | self-referential RTL when we will be substituting I0SRC for I0DEST | 61 | self-referential RTL when we will be substituting I0SRC for I0DEST |
| 62 | later. */ | 62 | later. */ |
| @@ -65,7 +65,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 65 | i0_feeds_i1_n && i0dest_in_i0src); | 65 | i0_feeds_i1_n && i0dest_in_i0src); |
| 66 | substed_i1 = 1; | 66 | substed_i1 = 1; |
| 67 | 67 | ||
| 68 | @@ -3198,7 +3198,7 @@ | 68 | @@ -3214,7 +3214,7 @@ |
| 69 | 69 | ||
| 70 | n_occurrences = 0; | 70 | n_occurrences = 0; |
| 71 | subst_low_luid = DF_INSN_LUID (i0); | 71 | subst_low_luid = DF_INSN_LUID (i0); |
| @@ -74,16 +74,16 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 74 | substed_i0 = 1; | 74 | substed_i0 = 1; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | @@ -3260,7 +3260,7 @@ | 77 | @@ -3276,7 +3276,7 @@ |
| 78 | { | 78 | { |
| 79 | rtx t = i1pat; | 79 | rtx t = i1pat; |
| 80 | if (i0_feeds_i1_n) | 80 | if (i0_feeds_i1_n) |
| 81 | - t = subst (t, i0dest, i0src, 0, 0); | 81 | - t = subst (t, i0dest, i0src_copy ? i0src_copy : i0src, 0, 0); |
| 82 | + t = subst (t, i0dest, i0src, 0, 0, 0); | 82 | + t = subst (t, i0dest, i0src_copy ? i0src_copy : i0src, 0, 0, 0); |
| 83 | 83 | ||
| 84 | XVECEXP (newpat, 0, --total_sets) = t; | 84 | XVECEXP (newpat, 0, --total_sets) = t; |
| 85 | } | 85 | } |
| 86 | @@ -3268,10 +3268,10 @@ | 86 | @@ -3284,10 +3284,10 @@ |
| 87 | { | 87 | { |
| 88 | rtx t = i2pat; | 88 | rtx t = i2pat; |
| 89 | if (i1_feeds_i2_n) | 89 | if (i1_feeds_i2_n) |
| @@ -91,12 +91,12 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 91 | + t = subst (t, i1dest, i1src_copy ? i1src_copy : i1src, 0, 0, | 91 | + t = subst (t, i1dest, i1src_copy ? i1src_copy : i1src, 0, 0, |
| 92 | i0_feeds_i1_n && i0dest_in_i0src); | 92 | i0_feeds_i1_n && i0dest_in_i0src); |
| 93 | if ((i0_feeds_i1_n && i1_feeds_i2_n) || i0_feeds_i2_n) | 93 | if ((i0_feeds_i1_n && i1_feeds_i2_n) || i0_feeds_i2_n) |
| 94 | - t = subst (t, i0dest, i0src, 0, 0); | 94 | - t = subst (t, i0dest, i0src_copy2 ? i0src_copy2 : i0src, 0, 0); |
| 95 | + t = subst (t, i0dest, i0src, 0, 0, 0); | 95 | + t = subst (t, i0dest, i0src_copy2 ? i0src_copy2 : i0src, 0, 0, 0); |
| 96 | 96 | ||
| 97 | XVECEXP (newpat, 0, --total_sets) = t; | 97 | XVECEXP (newpat, 0, --total_sets) = t; |
| 98 | } | 98 | } |
| 99 | @@ -4943,11 +4943,13 @@ | 99 | @@ -4959,11 +4959,13 @@ |
| 100 | 100 | ||
| 101 | IN_DEST is nonzero if we are processing the SET_DEST of a SET. | 101 | IN_DEST is nonzero if we are processing the SET_DEST of a SET. |
| 102 | 102 | ||
| @@ -111,7 +111,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 111 | { | 111 | { |
| 112 | enum rtx_code code = GET_CODE (x); | 112 | enum rtx_code code = GET_CODE (x); |
| 113 | enum machine_mode op0_mode = VOIDmode; | 113 | enum machine_mode op0_mode = VOIDmode; |
| 114 | @@ -5008,7 +5010,7 @@ | 114 | @@ -5024,7 +5026,7 @@ |
| 115 | && GET_CODE (XVECEXP (x, 0, 0)) == SET | 115 | && GET_CODE (XVECEXP (x, 0, 0)) == SET |
| 116 | && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS) | 116 | && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS) |
| 117 | { | 117 | { |
| @@ -120,7 +120,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 120 | 120 | ||
| 121 | /* If this substitution failed, this whole thing fails. */ | 121 | /* If this substitution failed, this whole thing fails. */ |
| 122 | if (GET_CODE (new_rtx) == CLOBBER | 122 | if (GET_CODE (new_rtx) == CLOBBER |
| 123 | @@ -5025,7 +5027,7 @@ | 123 | @@ -5041,7 +5043,7 @@ |
| 124 | && GET_CODE (dest) != CC0 | 124 | && GET_CODE (dest) != CC0 |
| 125 | && GET_CODE (dest) != PC) | 125 | && GET_CODE (dest) != PC) |
| 126 | { | 126 | { |
| @@ -129,7 +129,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 129 | 129 | ||
| 130 | /* If this substitution failed, this whole thing fails. */ | 130 | /* If this substitution failed, this whole thing fails. */ |
| 131 | if (GET_CODE (new_rtx) == CLOBBER | 131 | if (GET_CODE (new_rtx) == CLOBBER |
| 132 | @@ -5071,8 +5073,8 @@ | 132 | @@ -5087,8 +5089,8 @@ |
| 133 | } | 133 | } |
| 134 | else | 134 | else |
| 135 | { | 135 | { |
| @@ -140,7 +140,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 140 | 140 | ||
| 141 | /* If this substitution failed, this whole thing | 141 | /* If this substitution failed, this whole thing |
| 142 | fails. */ | 142 | fails. */ |
| 143 | @@ -5149,7 +5151,9 @@ | 143 | @@ -5165,7 +5167,9 @@ |
| 144 | && (code == SUBREG || code == STRICT_LOW_PART | 144 | && (code == SUBREG || code == STRICT_LOW_PART |
| 145 | || code == ZERO_EXTRACT)) | 145 | || code == ZERO_EXTRACT)) |
| 146 | || code == SET) | 146 | || code == SET) |
| @@ -151,7 +151,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 151 | 151 | ||
| 152 | /* If we found that we will have to reject this combination, | 152 | /* If we found that we will have to reject this combination, |
| 153 | indicate that by returning the CLOBBER ourselves, rather than | 153 | indicate that by returning the CLOBBER ourselves, rather than |
| 154 | @@ -5206,7 +5210,7 @@ | 154 | @@ -5222,7 +5226,7 @@ |
| 155 | /* If X is sufficiently simple, don't bother trying to do anything | 155 | /* If X is sufficiently simple, don't bother trying to do anything |
| 156 | with it. */ | 156 | with it. */ |
| 157 | if (code != CONST_INT && code != REG && code != CLOBBER) | 157 | if (code != CONST_INT && code != REG && code != CLOBBER) |
| @@ -160,7 +160,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 160 | 160 | ||
| 161 | if (GET_CODE (x) == code) | 161 | if (GET_CODE (x) == code) |
| 162 | break; | 162 | break; |
| 163 | @@ -5226,10 +5230,12 @@ | 163 | @@ -5242,10 +5246,12 @@ |
| 164 | expression. | 164 | expression. |
| 165 | 165 | ||
| 166 | OP0_MODE is the original mode of XEXP (x, 0). IN_DEST is nonzero | 166 | OP0_MODE is the original mode of XEXP (x, 0). IN_DEST is nonzero |
| @@ -175,7 +175,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 175 | { | 175 | { |
| 176 | enum rtx_code code = GET_CODE (x); | 176 | enum rtx_code code = GET_CODE (x); |
| 177 | enum machine_mode mode = GET_MODE (x); | 177 | enum machine_mode mode = GET_MODE (x); |
| 178 | @@ -5284,8 +5290,8 @@ | 178 | @@ -5300,8 +5306,8 @@ |
| 179 | false arms to store-flag values. Be careful to use copy_rtx | 179 | false arms to store-flag values. Be careful to use copy_rtx |
| 180 | here since true_rtx or false_rtx might share RTL with x as a | 180 | here since true_rtx or false_rtx might share RTL with x as a |
| 181 | result of the if_then_else_cond call above. */ | 181 | result of the if_then_else_cond call above. */ |
| @@ -186,7 +186,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 186 | 186 | ||
| 187 | /* If true_rtx and false_rtx are not general_operands, an if_then_else | 187 | /* If true_rtx and false_rtx are not general_operands, an if_then_else |
| 188 | is unlikely to be simpler. */ | 188 | is unlikely to be simpler. */ |
| 189 | @@ -5629,7 +5635,7 @@ | 189 | @@ -5645,7 +5651,7 @@ |
| 190 | { | 190 | { |
| 191 | /* Try to simplify the expression further. */ | 191 | /* Try to simplify the expression further. */ |
| 192 | rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); | 192 | rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); |
| @@ -195,7 +195,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 195 | 195 | ||
| 196 | /* If we could, great. If not, do not go ahead with the IOR | 196 | /* If we could, great. If not, do not go ahead with the IOR |
| 197 | replacement, since PLUS appears in many special purpose | 197 | replacement, since PLUS appears in many special purpose |
| 198 | @@ -5722,7 +5728,16 @@ | 198 | @@ -5738,7 +5744,16 @@ |
| 199 | ZERO_EXTRACT is indeed appropriate, it will be placed back by | 199 | ZERO_EXTRACT is indeed appropriate, it will be placed back by |
| 200 | the call to make_compound_operation in the SET case. */ | 200 | the call to make_compound_operation in the SET case. */ |
| 201 | 201 | ||
| @@ -213,7 +213,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 213 | && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT | 213 | && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT |
| 214 | && op1 == const0_rtx | 214 | && op1 == const0_rtx |
| 215 | && mode == GET_MODE (op0) | 215 | && mode == GET_MODE (op0) |
| 216 | @@ -5768,7 +5783,10 @@ | 216 | @@ -5784,7 +5799,10 @@ |
| 217 | 217 | ||
| 218 | /* If STORE_FLAG_VALUE is -1, we have cases similar to | 218 | /* If STORE_FLAG_VALUE is -1, we have cases similar to |
| 219 | those above. */ | 219 | those above. */ |
| @@ -225,7 +225,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 225 | && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT | 225 | && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT |
| 226 | && op1 == const0_rtx | 226 | && op1 == const0_rtx |
| 227 | && (num_sign_bit_copies (op0, mode) | 227 | && (num_sign_bit_copies (op0, mode) |
| 228 | @@ -5966,11 +5984,11 @@ | 228 | @@ -5982,11 +6000,11 @@ |
| 229 | if (reg_mentioned_p (from, true_rtx)) | 229 | if (reg_mentioned_p (from, true_rtx)) |
| 230 | true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code, | 230 | true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code, |
| 231 | from, true_val), | 231 | from, true_val), |
| @@ -239,7 +239,7 @@ Index: gcc-4_6-branch/gcc/combine.c | |||
| 239 | 239 | ||
| 240 | SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx); | 240 | SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx); |
| 241 | SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx); | 241 | SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx); |
| 242 | @@ -6187,11 +6205,11 @@ | 242 | @@ -6203,11 +6221,11 @@ |
| 243 | { | 243 | { |
| 244 | temp = subst (simplify_gen_relational (true_code, m, VOIDmode, | 244 | temp = subst (simplify_gen_relational (true_code, m, VOIDmode, |
| 245 | cond_op0, cond_op1), | 245 | cond_op0, cond_op1), |
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106827.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106827.patch index d49ebab600..28caa40076 100644 --- a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106827.patch +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106827.patch | |||
| @@ -37,8 +37,10 @@ | |||
| 37 | * config/arm/arm.md (*arm_movqi_insn): Compute attr "length". | 37 | * config/arm/arm.md (*arm_movqi_insn): Compute attr "length". |
| 38 | 38 | ||
| 39 | === modified file 'gcc/config/arm/arm-protos.h' | 39 | === modified file 'gcc/config/arm/arm-protos.h' |
| 40 | --- old/gcc/config/arm/arm-protos.h 2011-10-03 09:46:40 +0000 | 40 | Index: gcc-4_6-branch/gcc/config/arm/arm-protos.h |
| 41 | +++ new/gcc/config/arm/arm-protos.h 2011-10-11 01:56:19 +0000 | 41 | =================================================================== |
| 42 | --- gcc-4_6-branch.orig/gcc/config/arm/arm-protos.h 2012-03-05 16:07:15.000000000 -0800 | ||
| 43 | +++ gcc-4_6-branch/gcc/config/arm/arm-protos.h 2012-03-05 16:07:50.392936694 -0800 | ||
| 42 | @@ -59,6 +59,7 @@ | 44 | @@ -59,6 +59,7 @@ |
| 43 | int); | 45 | int); |
| 44 | extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int, | 46 | extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int, |
| @@ -47,10 +49,10 @@ | |||
| 47 | extern int arm_const_double_rtx (rtx); | 49 | extern int arm_const_double_rtx (rtx); |
| 48 | extern int neg_const_double_rtx_ok_for_fpa (rtx); | 50 | extern int neg_const_double_rtx_ok_for_fpa (rtx); |
| 49 | extern int vfp3_const_double_rtx (rtx); | 51 | extern int vfp3_const_double_rtx (rtx); |
| 50 | 52 | Index: gcc-4_6-branch/gcc/config/arm/arm.c | |
| 51 | === modified file 'gcc/config/arm/arm.c' | 53 | =================================================================== |
| 52 | --- old/gcc/config/arm/arm.c 2011-10-03 09:46:40 +0000 | 54 | --- gcc-4_6-branch.orig/gcc/config/arm/arm.c 2012-03-05 16:07:15.000000000 -0800 |
| 53 | +++ new/gcc/config/arm/arm.c 2011-10-11 02:31:01 +0000 | 55 | +++ gcc-4_6-branch/gcc/config/arm/arm.c 2012-03-05 16:07:50.400936694 -0800 |
| 54 | @@ -2065,6 +2065,28 @@ | 56 | @@ -2065,6 +2065,28 @@ |
| 55 | fix_cm3_ldrd = 0; | 57 | fix_cm3_ldrd = 0; |
| 56 | } | 58 | } |
| @@ -80,7 +82,7 @@ | |||
| 80 | if (TARGET_THUMB1 && flag_schedule_insns) | 82 | if (TARGET_THUMB1 && flag_schedule_insns) |
| 81 | { | 83 | { |
| 82 | /* Don't warn since it's on by default in -O2. */ | 84 | /* Don't warn since it's on by default in -O2. */ |
| 83 | @@ -6106,7 +6128,7 @@ | 85 | @@ -6123,7 +6145,7 @@ |
| 84 | addresses based on the frame pointer or arg pointer until the | 86 | addresses based on the frame pointer or arg pointer until the |
| 85 | reload pass starts. This is so that eliminating such addresses | 87 | reload pass starts. This is so that eliminating such addresses |
| 86 | into stack based ones won't produce impossible code. */ | 88 | into stack based ones won't produce impossible code. */ |
| @@ -89,7 +91,7 @@ | |||
| 89 | thumb1_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) | 91 | thumb1_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) |
| 90 | { | 92 | { |
| 91 | /* ??? Not clear if this is right. Experiment. */ | 93 | /* ??? Not clear if this is right. Experiment. */ |
| 92 | @@ -22226,6 +22248,10 @@ | 94 | @@ -22251,6 +22273,10 @@ |
| 93 | val = 6; | 95 | val = 6; |
| 94 | asm_fprintf (asm_out_file, "\t.eabi_attribute 30, %d\n", val); | 96 | asm_fprintf (asm_out_file, "\t.eabi_attribute 30, %d\n", val); |
| 95 | 97 | ||
| @@ -100,22 +102,22 @@ | |||
| 100 | /* Tag_ABI_FP_16bit_format. */ | 102 | /* Tag_ABI_FP_16bit_format. */ |
| 101 | if (arm_fp16_format) | 103 | if (arm_fp16_format) |
| 102 | asm_fprintf (asm_out_file, "\t.eabi_attribute 38, %d\n", | 104 | asm_fprintf (asm_out_file, "\t.eabi_attribute 38, %d\n", |
| 103 | 105 | Index: gcc-4_6-branch/gcc/config/arm/arm.md | |
| 104 | === modified file 'gcc/config/arm/arm.md' | 106 | =================================================================== |
| 105 | --- old/gcc/config/arm/arm.md 2011-10-03 09:47:33 +0000 | 107 | --- gcc-4_6-branch.orig/gcc/config/arm/arm.md 2012-03-05 16:07:15.000000000 -0800 |
| 106 | +++ new/gcc/config/arm/arm.md 2011-10-11 02:31:01 +0000 | 108 | +++ gcc-4_6-branch/gcc/config/arm/arm.md 2012-03-05 16:09:26.284941314 -0800 |
| 107 | @@ -113,6 +113,10 @@ | 109 | @@ -114,6 +114,10 @@ |
| 108 | (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from | ||
| 109 | ; another symbolic address. | 110 | ; another symbolic address. |
| 110 | (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier. | 111 | (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier. |
| 111 | + (UNSPEC_UNALIGNED_LOAD 29) ; Used to represent ldr/ldrh instructions that access | 112 | (UNSPEC_PIC_UNIFIED 29) ; Create a common pic addressing form. |
| 113 | + (UNSPEC_UNALIGNED_LOAD 30) ; Used to represent ldr/ldrh instructions that access | ||
| 112 | + ; unaligned locations, on architectures which support | 114 | + ; unaligned locations, on architectures which support |
| 113 | + ; that. | 115 | + ; that. |
| 114 | + (UNSPEC_UNALIGNED_STORE 30) ; Same for str/strh. | 116 | + (UNSPEC_UNALIGNED_STORE 31) ; Same for str/strh. |
| 115 | ] | 117 | ] |
| 116 | ) | 118 | ) |
| 117 | 119 | ||
| 118 | @@ -2463,10 +2467,10 @@ | 120 | @@ -2461,10 +2465,10 @@ |
| 119 | ;;; this insv pattern, so this pattern needs to be reevalutated. | 121 | ;;; this insv pattern, so this pattern needs to be reevalutated. |
| 120 | 122 | ||
| 121 | (define_expand "insv" | 123 | (define_expand "insv" |
| @@ -130,51 +132,59 @@ | |||
| 130 | "TARGET_ARM || arm_arch_thumb2" | 132 | "TARGET_ARM || arm_arch_thumb2" |
| 131 | " | 133 | " |
| 132 | { | 134 | { |
| 133 | @@ -2477,35 +2481,70 @@ | 135 | @@ -2475,35 +2479,70 @@ |
| 134 | 136 | ||
| 135 | if (arm_arch_thumb2) | 137 | if (arm_arch_thumb2) |
| 136 | { | 138 | { |
| 137 | - bool use_bfi = TRUE; | 139 | - bool use_bfi = TRUE; |
| 138 | - | 140 | - |
| 139 | - if (GET_CODE (operands[3]) == CONST_INT) | 141 | - if (GET_CODE (operands[3]) == CONST_INT) |
| 140 | - { | ||
| 141 | - HOST_WIDE_INT val = INTVAL (operands[3]) & mask; | ||
| 142 | - | ||
| 143 | - if (val == 0) | ||
| 144 | - { | ||
| 145 | - emit_insn (gen_insv_zero (operands[0], operands[1], | ||
| 146 | - operands[2])); | ||
| 147 | + if (unaligned_access && MEM_P (operands[0]) | 142 | + if (unaligned_access && MEM_P (operands[0]) |
| 148 | + && s_register_operand (operands[3], GET_MODE (operands[3])) | 143 | + && s_register_operand (operands[3], GET_MODE (operands[3])) |
| 149 | + && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0) | 144 | + && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0) |
| 150 | + { | 145 | { |
| 146 | - HOST_WIDE_INT val = INTVAL (operands[3]) & mask; | ||
| 151 | + rtx base_addr; | 147 | + rtx base_addr; |
| 152 | + | 148 | + |
| 153 | + if (BYTES_BIG_ENDIAN) | 149 | + if (BYTES_BIG_ENDIAN) |
| 154 | + start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width | 150 | + start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width |
| 155 | + - start_bit; | 151 | + - start_bit; |
| 156 | + | 152 | |
| 153 | - if (val == 0) | ||
| 157 | + if (width == 32) | 154 | + if (width == 32) |
| 158 | + { | 155 | { |
| 156 | - emit_insn (gen_insv_zero (operands[0], operands[1], | ||
| 157 | - operands[2])); | ||
| 158 | - DONE; | ||
| 159 | + base_addr = adjust_address (operands[0], SImode, | 159 | + base_addr = adjust_address (operands[0], SImode, |
| 160 | + start_bit / BITS_PER_UNIT); | 160 | + start_bit / BITS_PER_UNIT); |
| 161 | + emit_insn (gen_unaligned_storesi (base_addr, operands[3])); | 161 | + emit_insn (gen_unaligned_storesi (base_addr, operands[3])); |
| 162 | + } | 162 | } |
| 163 | + else | 163 | + else |
| 164 | + { | 164 | + { |
| 165 | + rtx tmp = gen_reg_rtx (HImode); | 165 | + rtx tmp = gen_reg_rtx (HImode); |
| 166 | + | 166 | |
| 167 | - /* See if the set can be done with a single orr instruction. */ | ||
| 168 | - if (val == mask && const_ok_for_arm (val << start_bit)) | ||
| 169 | - use_bfi = FALSE; | ||
| 167 | + base_addr = adjust_address (operands[0], HImode, | 170 | + base_addr = adjust_address (operands[0], HImode, |
| 168 | + start_bit / BITS_PER_UNIT); | 171 | + start_bit / BITS_PER_UNIT); |
| 169 | + emit_move_insn (tmp, gen_lowpart (HImode, operands[3])); | 172 | + emit_move_insn (tmp, gen_lowpart (HImode, operands[3])); |
| 170 | + emit_insn (gen_unaligned_storehi (base_addr, tmp)); | 173 | + emit_insn (gen_unaligned_storehi (base_addr, tmp)); |
| 171 | + } | 174 | + } |
| 172 | + DONE; | 175 | + DONE; |
| 173 | + } | 176 | } |
| 177 | - | ||
| 178 | - if (use_bfi) | ||
| 174 | + else if (s_register_operand (operands[0], GET_MODE (operands[0]))) | 179 | + else if (s_register_operand (operands[0], GET_MODE (operands[0]))) |
| 175 | + { | 180 | { |
| 181 | - if (GET_CODE (operands[3]) != REG) | ||
| 182 | - operands[3] = force_reg (SImode, operands[3]); | ||
| 176 | + bool use_bfi = TRUE; | 183 | + bool use_bfi = TRUE; |
| 177 | + | 184 | |
| 185 | - emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2], | ||
| 186 | - operands[3])); | ||
| 187 | - DONE; | ||
| 178 | + if (GET_CODE (operands[3]) == CONST_INT) | 188 | + if (GET_CODE (operands[3]) == CONST_INT) |
| 179 | + { | 189 | + { |
| 180 | + HOST_WIDE_INT val = INTVAL (operands[3]) & mask; | 190 | + HOST_WIDE_INT val = INTVAL (operands[3]) & mask; |
| @@ -198,24 +208,9 @@ | |||
| 198 | + | 208 | + |
| 199 | + emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2], | 209 | + emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2], |
| 200 | + operands[3])); | 210 | + operands[3])); |
| 201 | DONE; | 211 | + DONE; |
| 202 | } | 212 | + } |
| 203 | - | 213 | } |
| 204 | - /* See if the set can be done with a single orr instruction. */ | ||
| 205 | - if (val == mask && const_ok_for_arm (val << start_bit)) | ||
| 206 | - use_bfi = FALSE; | ||
| 207 | - } | ||
| 208 | - | ||
| 209 | - if (use_bfi) | ||
| 210 | - { | ||
| 211 | - if (GET_CODE (operands[3]) != REG) | ||
| 212 | - operands[3] = force_reg (SImode, operands[3]); | ||
| 213 | - | ||
| 214 | - emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2], | ||
| 215 | - operands[3])); | ||
| 216 | - DONE; | ||
| 217 | - } | ||
| 218 | + } | ||
| 219 | + else | 214 | + else |
| 220 | + FAIL; | 215 | + FAIL; |
| 221 | } | 216 | } |
| @@ -226,7 +221,7 @@ | |||
| 226 | target = copy_rtx (operands[0]); | 221 | target = copy_rtx (operands[0]); |
| 227 | /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical | 222 | /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical |
| 228 | subreg as the final target. */ | 223 | subreg as the final target. */ |
| 229 | @@ -3697,12 +3736,10 @@ | 224 | @@ -3695,12 +3734,10 @@ |
| 230 | ;; to reduce register pressure later on. | 225 | ;; to reduce register pressure later on. |
| 231 | 226 | ||
| 232 | (define_expand "extzv" | 227 | (define_expand "extzv" |
| @@ -243,7 +238,7 @@ | |||
| 243 | "TARGET_THUMB1 || arm_arch_thumb2" | 238 | "TARGET_THUMB1 || arm_arch_thumb2" |
| 244 | " | 239 | " |
| 245 | { | 240 | { |
| 246 | @@ -3711,10 +3748,57 @@ | 241 | @@ -3709,10 +3746,57 @@ |
| 247 | 242 | ||
| 248 | if (arm_arch_thumb2) | 243 | if (arm_arch_thumb2) |
| 249 | { | 244 | { |
| @@ -304,7 +299,7 @@ | |||
| 304 | 299 | ||
| 305 | operands[3] = GEN_INT (rshift); | 300 | operands[3] = GEN_INT (rshift); |
| 306 | 301 | ||
| 307 | @@ -3724,12 +3808,154 @@ | 302 | @@ -3722,12 +3806,154 @@ |
| 308 | DONE; | 303 | DONE; |
| 309 | } | 304 | } |
| 310 | 305 | ||
| @@ -462,7 +457,7 @@ | |||
| 462 | [(set (match_operand:SI 0 "s_register_operand" "=r") | 457 | [(set (match_operand:SI 0 "s_register_operand" "=r") |
| 463 | (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") | 458 | (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") |
| 464 | (match_operand:SI 2 "const_int_operand" "M") | 459 | (match_operand:SI 2 "const_int_operand" "M") |
| 465 | @@ -6038,8 +6264,8 @@ | 460 | @@ -6069,8 +6295,8 @@ |
| 466 | 461 | ||
| 467 | 462 | ||
| 468 | (define_insn "*arm_movqi_insn" | 463 | (define_insn "*arm_movqi_insn" |
| @@ -473,7 +468,7 @@ | |||
| 473 | "TARGET_32BIT | 468 | "TARGET_32BIT |
| 474 | && ( register_operand (operands[0], QImode) | 469 | && ( register_operand (operands[0], QImode) |
| 475 | || register_operand (operands[1], QImode))" | 470 | || register_operand (operands[1], QImode))" |
| 476 | @@ -6047,10 +6273,14 @@ | 471 | @@ -6078,10 +6304,14 @@ |
| 477 | mov%?\\t%0, %1 | 472 | mov%?\\t%0, %1 |
| 478 | mvn%?\\t%0, #%B1 | 473 | mvn%?\\t%0, #%B1 |
| 479 | ldr%(b%)\\t%0, %1 | 474 | ldr%(b%)\\t%0, %1 |
| @@ -491,10 +486,10 @@ | |||
| 491 | ) | 486 | ) |
| 492 | 487 | ||
| 493 | (define_insn "*thumb1_movqi_insn" | 488 | (define_insn "*thumb1_movqi_insn" |
| 494 | 489 | Index: gcc-4_6-branch/gcc/config/arm/arm.opt | |
| 495 | === modified file 'gcc/config/arm/arm.opt' | 490 | =================================================================== |
| 496 | --- old/gcc/config/arm/arm.opt 2011-09-19 07:44:24 +0000 | 491 | --- gcc-4_6-branch.orig/gcc/config/arm/arm.opt 2012-03-05 16:07:14.000000000 -0800 |
| 497 | +++ new/gcc/config/arm/arm.opt 2011-10-11 02:31:01 +0000 | 492 | +++ gcc-4_6-branch/gcc/config/arm/arm.opt 2012-03-05 16:07:50.404936697 -0800 |
| 498 | @@ -173,3 +173,7 @@ | 493 | @@ -173,3 +173,7 @@ |
| 499 | Target Report Var(fix_cm3_ldrd) Init(2) | 494 | Target Report Var(fix_cm3_ldrd) Init(2) |
| 500 | Avoid overlapping destination and address registers on LDRD instructions | 495 | Avoid overlapping destination and address registers on LDRD instructions |
| @@ -503,10 +498,10 @@ | |||
| 503 | +munaligned-access | 498 | +munaligned-access |
| 504 | +Target Report Var(unaligned_access) Init(2) | 499 | +Target Report Var(unaligned_access) Init(2) |
| 505 | +Enable unaligned word and halfword accesses to packed data. | 500 | +Enable unaligned word and halfword accesses to packed data. |
| 506 | 501 | Index: gcc-4_6-branch/gcc/config/arm/constraints.md | |
| 507 | === modified file 'gcc/config/arm/constraints.md' | 502 | =================================================================== |
| 508 | --- old/gcc/config/arm/constraints.md 2011-09-12 14:14:00 +0000 | 503 | --- gcc-4_6-branch.orig/gcc/config/arm/constraints.md 2012-03-05 16:07:14.000000000 -0800 |
| 509 | +++ new/gcc/config/arm/constraints.md 2011-10-11 02:31:01 +0000 | 504 | +++ gcc-4_6-branch/gcc/config/arm/constraints.md 2012-03-05 16:07:50.404936697 -0800 |
| 510 | @@ -36,6 +36,7 @@ | 505 | @@ -36,6 +36,7 @@ |
| 511 | ;; The following memory constraints have been used: | 506 | ;; The following memory constraints have been used: |
| 512 | ;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us | 507 | ;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us |
| @@ -543,10 +538,10 @@ | |||
| 543 | ;; We used to have constraint letters for S and R in ARM state, but | 538 | ;; We used to have constraint letters for S and R in ARM state, but |
| 544 | ;; all uses of these now appear to have been removed. | 539 | ;; all uses of these now appear to have been removed. |
| 545 | 540 | ||
| 546 | 541 | Index: gcc-4_6-branch/gcc/expmed.c | |
| 547 | === modified file 'gcc/expmed.c' | 542 | =================================================================== |
| 548 | --- old/gcc/expmed.c 2011-05-22 19:02:59 +0000 | 543 | --- gcc-4_6-branch.orig/gcc/expmed.c 2012-01-04 15:37:51.000000000 -0800 |
| 549 | +++ new/gcc/expmed.c 2011-10-11 02:31:01 +0000 | 544 | +++ gcc-4_6-branch/gcc/expmed.c 2012-03-05 16:07:50.404936697 -0800 |
| 550 | @@ -657,6 +657,10 @@ | 545 | @@ -657,6 +657,10 @@ |
| 551 | && GET_MODE (value) != BLKmode | 546 | && GET_MODE (value) != BLKmode |
| 552 | && bitsize > 0 | 547 | && bitsize > 0 |
| @@ -625,4 +620,3 @@ | |||
| 625 | if (xtarget == 0) | 620 | if (xtarget == 0) |
| 626 | xtarget = xspec_target = gen_reg_rtx (tmode); | 621 | xtarget = xspec_target = gen_reg_rtx (tmode); |
| 627 | 622 | ||
| 628 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106842.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106842.patch index 74f139d33a..2cf2741ba6 100644 --- a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106842.patch +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106842.patch | |||
| @@ -48,8 +48,10 @@ | |||
| 48 | Return true for NEON. | 48 | Return true for NEON. |
| 49 | 49 | ||
| 50 | === modified file 'gcc/testsuite/gcc.dg/vect/pr30858.c' | 50 | === modified file 'gcc/testsuite/gcc.dg/vect/pr30858.c' |
| 51 | --- old/gcc/testsuite/gcc.dg/vect/pr30858.c 2007-02-22 08:16:18 +0000 | 51 | Index: gcc-4_6-branch/gcc/testsuite/gcc.dg/vect/pr30858.c |
| 52 | +++ new/gcc/testsuite/gcc.dg/vect/pr30858.c 2011-11-20 09:11:09 +0000 | 52 | =================================================================== |
| 53 | --- gcc-4_6-branch.orig/gcc/testsuite/gcc.dg/vect/pr30858.c 2012-01-04 15:33:52.000000000 -0800 | ||
| 54 | +++ gcc-4_6-branch/gcc/testsuite/gcc.dg/vect/pr30858.c 2012-03-05 16:23:47.748983031 -0800 | ||
| 53 | @@ -11,5 +11,6 @@ | 55 | @@ -11,5 +11,6 @@ |
| 54 | } | 56 | } |
| 55 | 57 | ||
| @@ -58,10 +60,10 @@ | |||
| 58 | +/* { dg-final { scan-tree-dump-times "Unknown def-use cycle pattern." 1 "vect" { xfail vect_multiple_sizes } } } */ | 60 | +/* { dg-final { scan-tree-dump-times "Unknown def-use cycle pattern." 1 "vect" { xfail vect_multiple_sizes } } } */ |
| 59 | +/* { dg-final { scan-tree-dump-times "Unknown def-use cycle pattern." 2 "vect" { target vect_multiple_sizes } } } */ | 61 | +/* { dg-final { scan-tree-dump-times "Unknown def-use cycle pattern." 2 "vect" { target vect_multiple_sizes } } } */ |
| 60 | /* { dg-final { cleanup-tree-dump "vect" } } */ | 62 | /* { dg-final { cleanup-tree-dump "vect" } } */ |
| 61 | 63 | Index: gcc-4_6-branch/gcc/testsuite/gcc.dg/vect/vect-cond-8a.c | |
| 62 | === added file 'gcc/testsuite/gcc.dg/vect/vect-cond-8a.c' | 64 | =================================================================== |
| 63 | --- old/gcc/testsuite/gcc.dg/vect/vect-cond-8a.c 1970-01-01 00:00:00 +0000 | 65 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
| 64 | +++ new/gcc/testsuite/gcc.dg/vect/vect-cond-8a.c 2011-11-20 09:11:09 +0000 | 66 | +++ gcc-4_6-branch/gcc/testsuite/gcc.dg/vect/vect-cond-8a.c 2012-03-05 16:23:47.748983031 -0800 |
| 65 | @@ -0,0 +1,75 @@ | 67 | @@ -0,0 +1,75 @@ |
| 66 | +/* { dg-require-effective-target vect_condition } */ | 68 | +/* { dg-require-effective-target vect_condition } */ |
| 67 | + | 69 | + |
| @@ -138,24 +140,10 @@ | |||
| 138 | + | 140 | + |
| 139 | +/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops" 3 "vect" } } */ | 141 | +/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops" 3 "vect" } } */ |
| 140 | +/* { dg-final { cleanup-tree-dump "vect" } } */ | 142 | +/* { dg-final { cleanup-tree-dump "vect" } } */ |
| 141 | 143 | Index: gcc-4_6-branch/gcc/tree-vect-patterns.c | |
| 142 | === modified file 'gcc/testsuite/lib/target-supports.exp' | 144 | =================================================================== |
| 143 | --- old/gcc/testsuite/lib/target-supports.exp 2011-11-21 01:45:54 +0000 | 145 | --- gcc-4_6-branch.orig/gcc/tree-vect-patterns.c 2012-03-05 16:23:10.000000000 -0800 |
| 144 | +++ new/gcc/testsuite/lib/target-supports.exp 2011-11-22 16:52:23 +0000 | 146 | +++ gcc-4_6-branch/gcc/tree-vect-patterns.c 2012-03-05 16:23:47.748983031 -0800 |
| 145 | @@ -3150,7 +3150,8 @@ | ||
| 146 | || [istarget ia64-*-*] | ||
| 147 | || [istarget i?86-*-*] | ||
| 148 | || [istarget spu-*-*] | ||
| 149 | - || [istarget x86_64-*-*] } { | ||
| 150 | + || [istarget x86_64-*-*] | ||
| 151 | + || ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } { | ||
| 152 | set et_vect_cond_saved 1 | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | === modified file 'gcc/tree-vect-patterns.c' | ||
| 157 | --- old/gcc/tree-vect-patterns.c 2011-10-23 13:33:07 +0000 | ||
| 158 | +++ new/gcc/tree-vect-patterns.c 2011-11-20 09:11:09 +0000 | ||
| 159 | @@ -50,13 +50,16 @@ | 147 | @@ -50,13 +50,16 @@ |
| 160 | tree *); | 148 | tree *); |
| 161 | static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **, | 149 | static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **, |
| @@ -299,14 +287,14 @@ | |||
| 299 | def_stmt = STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info); | 287 | def_stmt = STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info); |
| 300 | - set_vinfo_for_stmt (def_stmt, | 288 | - set_vinfo_for_stmt (def_stmt, |
| 301 | - new_stmt_vec_info (def_stmt, loop_vinfo, NULL)); | 289 | - new_stmt_vec_info (def_stmt, loop_vinfo, NULL)); |
| 302 | + def_stmt_info = vinfo_for_stmt (def_stmt); | 290 | - gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); |
| 291 | def_stmt_info = vinfo_for_stmt (def_stmt); | ||
| 303 | + if (def_stmt_info == NULL) | 292 | + if (def_stmt_info == NULL) |
| 304 | + { | 293 | + { |
| 305 | + def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo, NULL); | 294 | + def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo, NULL); |
| 306 | + set_vinfo_for_stmt (def_stmt, def_stmt_info); | 295 | + set_vinfo_for_stmt (def_stmt, def_stmt_info); |
| 307 | + } | 296 | + } |
| 308 | gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); | 297 | + gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); |
| 309 | - def_stmt_info = vinfo_for_stmt (def_stmt); | ||
| 310 | STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt; | 298 | STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt; |
| 311 | STMT_VINFO_DEF_TYPE (def_stmt_info) | 299 | STMT_VINFO_DEF_TYPE (def_stmt_info) |
| 312 | = STMT_VINFO_DEF_TYPE (orig_stmt_info); | 300 | = STMT_VINFO_DEF_TYPE (orig_stmt_info); |
| @@ -316,10 +304,10 @@ | |||
| 316 | } | 304 | } |
| 317 | } | 305 | } |
| 318 | 306 | ||
| 319 | 307 | Index: gcc-4_6-branch/gcc/tree-vect-stmts.c | |
| 320 | === modified file 'gcc/tree-vect-stmts.c' | 308 | =================================================================== |
| 321 | --- old/gcc/tree-vect-stmts.c 2011-11-14 11:38:08 +0000 | 309 | --- gcc-4_6-branch.orig/gcc/tree-vect-stmts.c 2012-03-05 16:23:11.000000000 -0800 |
| 322 | +++ new/gcc/tree-vect-stmts.c 2011-11-22 16:52:23 +0000 | 310 | +++ gcc-4_6-branch/gcc/tree-vect-stmts.c 2012-03-05 16:23:47.748983031 -0800 |
| 323 | @@ -655,20 +655,40 @@ | 311 | @@ -655,20 +655,40 @@ |
| 324 | tree rhs = gimple_assign_rhs1 (stmt); | 312 | tree rhs = gimple_assign_rhs1 (stmt); |
| 325 | unsigned int op_num; | 313 | unsigned int op_num; |
| @@ -372,10 +360,10 @@ | |||
| 372 | break; | 360 | break; |
| 373 | 361 | ||
| 374 | case GIMPLE_BINARY_RHS: | 362 | case GIMPLE_BINARY_RHS: |
| 375 | 363 | Index: gcc-4_6-branch/gcc/tree-vectorizer.h | |
| 376 | === modified file 'gcc/tree-vectorizer.h' | 364 | =================================================================== |
| 377 | --- old/gcc/tree-vectorizer.h 2011-11-14 11:38:08 +0000 | 365 | --- gcc-4_6-branch.orig/gcc/tree-vectorizer.h 2012-03-05 16:23:11.000000000 -0800 |
| 378 | +++ new/gcc/tree-vectorizer.h 2011-11-22 16:52:23 +0000 | 366 | +++ gcc-4_6-branch/gcc/tree-vectorizer.h 2012-03-05 16:23:47.748983031 -0800 |
| 379 | @@ -917,7 +917,7 @@ | 367 | @@ -917,7 +917,7 @@ |
| 380 | Additional pattern recognition functions can (and will) be added | 368 | Additional pattern recognition functions can (and will) be added |
| 381 | in the future. */ | 369 | in the future. */ |
| @@ -385,4 +373,3 @@ | |||
| 385 | void vect_pattern_recog (loop_vec_info); | 373 | void vect_pattern_recog (loop_vec_info); |
| 386 | 374 | ||
| 387 | /* In tree-vectorizer.c. */ | 375 | /* In tree-vectorizer.c. */ |
| 388 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106854.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106854.patch deleted file mode 100644 index 208ba0e78a..0000000000 --- a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106854.patch +++ /dev/null | |||
| @@ -1,354 +0,0 @@ | |||
| 1 | 2011-12-30 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 2 | |||
| 3 | gcc/ | ||
| 4 | Backport from mainline: | ||
| 5 | |||
| 6 | 2011-10-12 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 7 | |||
| 8 | * expr.h (copy_blkmode_to_reg): Declare. | ||
| 9 | * expr.c (copy_blkmode_to_reg): New function. | ||
| 10 | (expand_assignment): Don't expand register RESULT_DECLs before | ||
| 11 | the lhs. Use copy_blkmode_to_reg to copy BLKmode values into a | ||
| 12 | RESULT_DECL register. | ||
| 13 | (expand_expr_real_1): Handle BLKmode decls when looking for promotion. | ||
| 14 | * stmt.c (expand_return): Move BLKmode-to-register code into | ||
| 15 | copy_blkmode_to_reg. | ||
| 16 | |||
| 17 | === modified file 'gcc/expr.c' | ||
| 18 | --- old/gcc/expr.c 2011-10-23 13:33:07 +0000 | ||
| 19 | +++ new/gcc/expr.c 2011-12-30 09:41:30 +0000 | ||
| 20 | @@ -2180,6 +2180,111 @@ | ||
| 21 | return tgtblk; | ||
| 22 | } | ||
| 23 | |||
| 24 | +/* Copy BLKmode value SRC into a register of mode MODE. Return the | ||
| 25 | + register if it contains any data, otherwise return null. | ||
| 26 | + | ||
| 27 | + This is used on targets that return BLKmode values in registers. */ | ||
| 28 | + | ||
| 29 | +rtx | ||
| 30 | +copy_blkmode_to_reg (enum machine_mode mode, tree src) | ||
| 31 | +{ | ||
| 32 | + int i, n_regs; | ||
| 33 | + unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0, bytes; | ||
| 34 | + unsigned int bitsize; | ||
| 35 | + rtx *dst_words, dst, x, src_word = NULL_RTX, dst_word = NULL_RTX; | ||
| 36 | + enum machine_mode dst_mode; | ||
| 37 | + | ||
| 38 | + gcc_assert (TYPE_MODE (TREE_TYPE (src)) == BLKmode); | ||
| 39 | + | ||
| 40 | + x = expand_normal (src); | ||
| 41 | + | ||
| 42 | + bytes = int_size_in_bytes (TREE_TYPE (src)); | ||
| 43 | + if (bytes == 0) | ||
| 44 | + return NULL_RTX; | ||
| 45 | + | ||
| 46 | + /* If the structure doesn't take up a whole number of words, see | ||
| 47 | + whether the register value should be padded on the left or on | ||
| 48 | + the right. Set PADDING_CORRECTION to the number of padding | ||
| 49 | + bits needed on the left side. | ||
| 50 | + | ||
| 51 | + In most ABIs, the structure will be returned at the least end of | ||
| 52 | + the register, which translates to right padding on little-endian | ||
| 53 | + targets and left padding on big-endian targets. The opposite | ||
| 54 | + holds if the structure is returned at the most significant | ||
| 55 | + end of the register. */ | ||
| 56 | + if (bytes % UNITS_PER_WORD != 0 | ||
| 57 | + && (targetm.calls.return_in_msb (TREE_TYPE (src)) | ||
| 58 | + ? !BYTES_BIG_ENDIAN | ||
| 59 | + : BYTES_BIG_ENDIAN)) | ||
| 60 | + padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) | ||
| 61 | + * BITS_PER_UNIT)); | ||
| 62 | + | ||
| 63 | + n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; | ||
| 64 | + dst_words = XALLOCAVEC (rtx, n_regs); | ||
| 65 | + bitsize = MIN (TYPE_ALIGN (TREE_TYPE (src)), BITS_PER_WORD); | ||
| 66 | + | ||
| 67 | + /* Copy the structure BITSIZE bits at a time. */ | ||
| 68 | + for (bitpos = 0, xbitpos = padding_correction; | ||
| 69 | + bitpos < bytes * BITS_PER_UNIT; | ||
| 70 | + bitpos += bitsize, xbitpos += bitsize) | ||
| 71 | + { | ||
| 72 | + /* We need a new destination pseudo each time xbitpos is | ||
| 73 | + on a word boundary and when xbitpos == padding_correction | ||
| 74 | + (the first time through). */ | ||
| 75 | + if (xbitpos % BITS_PER_WORD == 0 | ||
| 76 | + || xbitpos == padding_correction) | ||
| 77 | + { | ||
| 78 | + /* Generate an appropriate register. */ | ||
| 79 | + dst_word = gen_reg_rtx (word_mode); | ||
| 80 | + dst_words[xbitpos / BITS_PER_WORD] = dst_word; | ||
| 81 | + | ||
| 82 | + /* Clear the destination before we move anything into it. */ | ||
| 83 | + emit_move_insn (dst_word, CONST0_RTX (word_mode)); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + /* We need a new source operand each time bitpos is on a word | ||
| 87 | + boundary. */ | ||
| 88 | + if (bitpos % BITS_PER_WORD == 0) | ||
| 89 | + src_word = operand_subword_force (x, bitpos / BITS_PER_WORD, BLKmode); | ||
| 90 | + | ||
| 91 | + /* Use bitpos for the source extraction (left justified) and | ||
| 92 | + xbitpos for the destination store (right justified). */ | ||
| 93 | + store_bit_field (dst_word, bitsize, xbitpos % BITS_PER_WORD, word_mode, | ||
| 94 | + extract_bit_field (src_word, bitsize, | ||
| 95 | + bitpos % BITS_PER_WORD, 1, false, | ||
| 96 | + NULL_RTX, word_mode, word_mode)); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + if (mode == BLKmode) | ||
| 100 | + { | ||
| 101 | + /* Find the smallest integer mode large enough to hold the | ||
| 102 | + entire structure. */ | ||
| 103 | + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); | ||
| 104 | + mode != VOIDmode; | ||
| 105 | + mode = GET_MODE_WIDER_MODE (mode)) | ||
| 106 | + /* Have we found a large enough mode? */ | ||
| 107 | + if (GET_MODE_SIZE (mode) >= bytes) | ||
| 108 | + break; | ||
| 109 | + | ||
| 110 | + /* A suitable mode should have been found. */ | ||
| 111 | + gcc_assert (mode != VOIDmode); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode)) | ||
| 115 | + dst_mode = word_mode; | ||
| 116 | + else | ||
| 117 | + dst_mode = mode; | ||
| 118 | + dst = gen_reg_rtx (dst_mode); | ||
| 119 | + | ||
| 120 | + for (i = 0; i < n_regs; i++) | ||
| 121 | + emit_move_insn (operand_subword (dst, i, 0, dst_mode), dst_words[i]); | ||
| 122 | + | ||
| 123 | + if (mode != dst_mode) | ||
| 124 | + dst = gen_lowpart (mode, dst); | ||
| 125 | + | ||
| 126 | + return dst; | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | /* Add a USE expression for REG to the (possibly empty) list pointed | ||
| 130 | to by CALL_FUSAGE. REG must denote a hard register. */ | ||
| 131 | |||
| 132 | @@ -4382,7 +4487,9 @@ | ||
| 133 | if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from) | ||
| 134 | && COMPLETE_TYPE_P (TREE_TYPE (from)) | ||
| 135 | && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST | ||
| 136 | - && ! (((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL) | ||
| 137 | + && ! (((TREE_CODE (to) == VAR_DECL | ||
| 138 | + || TREE_CODE (to) == PARM_DECL | ||
| 139 | + || TREE_CODE (to) == RESULT_DECL) | ||
| 140 | && REG_P (DECL_RTL (to))) | ||
| 141 | || TREE_CODE (to) == SSA_NAME)) | ||
| 142 | { | ||
| 143 | @@ -4428,12 +4535,15 @@ | ||
| 144 | rtx temp; | ||
| 145 | |||
| 146 | push_temp_slots (); | ||
| 147 | - temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL); | ||
| 148 | + if (REG_P (to_rtx) && TYPE_MODE (TREE_TYPE (from)) == BLKmode) | ||
| 149 | + temp = copy_blkmode_to_reg (GET_MODE (to_rtx), from); | ||
| 150 | + else | ||
| 151 | + temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL); | ||
| 152 | |||
| 153 | if (GET_CODE (to_rtx) == PARALLEL) | ||
| 154 | emit_group_load (to_rtx, temp, TREE_TYPE (from), | ||
| 155 | int_size_in_bytes (TREE_TYPE (from))); | ||
| 156 | - else | ||
| 157 | + else if (temp) | ||
| 158 | emit_move_insn (to_rtx, temp); | ||
| 159 | |||
| 160 | preserve_temp_slots (to_rtx); | ||
| 161 | @@ -8567,10 +8677,15 @@ | ||
| 162 | return temp; | ||
| 163 | } | ||
| 164 | |||
| 165 | - /* If the mode of DECL_RTL does not match that of the decl, it | ||
| 166 | - must be a promoted value. We return a SUBREG of the wanted mode, | ||
| 167 | - but mark it so that we know that it was already extended. */ | ||
| 168 | - if (REG_P (decl_rtl) && GET_MODE (decl_rtl) != DECL_MODE (exp)) | ||
| 169 | + /* If the mode of DECL_RTL does not match that of the decl, | ||
| 170 | + there are two cases: we are dealing with a BLKmode value | ||
| 171 | + that is returned in a register, or we are dealing with | ||
| 172 | + a promoted value. In the latter case, return a SUBREG | ||
| 173 | + of the wanted mode, but mark it so that we know that it | ||
| 174 | + was already extended. */ | ||
| 175 | + if (REG_P (decl_rtl) | ||
| 176 | + && DECL_MODE (exp) != BLKmode | ||
| 177 | + && GET_MODE (decl_rtl) != DECL_MODE (exp)) | ||
| 178 | { | ||
| 179 | enum machine_mode pmode; | ||
| 180 | |||
| 181 | |||
| 182 | === modified file 'gcc/expr.h' | ||
| 183 | --- old/gcc/expr.h 2011-03-03 21:56:58 +0000 | ||
| 184 | +++ new/gcc/expr.h 2011-10-12 08:01:43 +0000 | ||
| 185 | @@ -324,6 +324,8 @@ | ||
| 186 | /* Copy BLKmode object from a set of registers. */ | ||
| 187 | extern rtx copy_blkmode_from_reg (rtx, rtx, tree); | ||
| 188 | |||
| 189 | +extern rtx copy_blkmode_to_reg (enum machine_mode, tree); | ||
| 190 | + | ||
| 191 | /* Mark REG as holding a parameter for the next CALL_INSN. */ | ||
| 192 | extern void use_reg (rtx *, rtx); | ||
| 193 | |||
| 194 | |||
| 195 | === modified file 'gcc/stmt.c' | ||
| 196 | --- old/gcc/stmt.c 2011-03-03 21:56:58 +0000 | ||
| 197 | +++ new/gcc/stmt.c 2011-10-12 08:01:43 +0000 | ||
| 198 | @@ -1684,119 +1684,21 @@ | ||
| 199 | expand_value_return (result_rtl); | ||
| 200 | |||
| 201 | /* If the result is an aggregate that is being returned in one (or more) | ||
| 202 | - registers, load the registers here. The compiler currently can't handle | ||
| 203 | - copying a BLKmode value into registers. We could put this code in a | ||
| 204 | - more general area (for use by everyone instead of just function | ||
| 205 | - call/return), but until this feature is generally usable it is kept here | ||
| 206 | - (and in expand_call). */ | ||
| 207 | + registers, load the registers here. */ | ||
| 208 | |||
| 209 | else if (retval_rhs != 0 | ||
| 210 | && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode | ||
| 211 | && REG_P (result_rtl)) | ||
| 212 | { | ||
| 213 | - int i; | ||
| 214 | - unsigned HOST_WIDE_INT bitpos, xbitpos; | ||
| 215 | - unsigned HOST_WIDE_INT padding_correction = 0; | ||
| 216 | - unsigned HOST_WIDE_INT bytes | ||
| 217 | - = int_size_in_bytes (TREE_TYPE (retval_rhs)); | ||
| 218 | - int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; | ||
| 219 | - unsigned int bitsize | ||
| 220 | - = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD); | ||
| 221 | - rtx *result_pseudos = XALLOCAVEC (rtx, n_regs); | ||
| 222 | - rtx result_reg, src = NULL_RTX, dst = NULL_RTX; | ||
| 223 | - rtx result_val = expand_normal (retval_rhs); | ||
| 224 | - enum machine_mode tmpmode, result_reg_mode; | ||
| 225 | - | ||
| 226 | - if (bytes == 0) | ||
| 227 | - { | ||
| 228 | - expand_null_return (); | ||
| 229 | - return; | ||
| 230 | - } | ||
| 231 | - | ||
| 232 | - /* If the structure doesn't take up a whole number of words, see | ||
| 233 | - whether the register value should be padded on the left or on | ||
| 234 | - the right. Set PADDING_CORRECTION to the number of padding | ||
| 235 | - bits needed on the left side. | ||
| 236 | - | ||
| 237 | - In most ABIs, the structure will be returned at the least end of | ||
| 238 | - the register, which translates to right padding on little-endian | ||
| 239 | - targets and left padding on big-endian targets. The opposite | ||
| 240 | - holds if the structure is returned at the most significant | ||
| 241 | - end of the register. */ | ||
| 242 | - if (bytes % UNITS_PER_WORD != 0 | ||
| 243 | - && (targetm.calls.return_in_msb (TREE_TYPE (retval_rhs)) | ||
| 244 | - ? !BYTES_BIG_ENDIAN | ||
| 245 | - : BYTES_BIG_ENDIAN)) | ||
| 246 | - padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) | ||
| 247 | - * BITS_PER_UNIT)); | ||
| 248 | - | ||
| 249 | - /* Copy the structure BITSIZE bits at a time. */ | ||
| 250 | - for (bitpos = 0, xbitpos = padding_correction; | ||
| 251 | - bitpos < bytes * BITS_PER_UNIT; | ||
| 252 | - bitpos += bitsize, xbitpos += bitsize) | ||
| 253 | - { | ||
| 254 | - /* We need a new destination pseudo each time xbitpos is | ||
| 255 | - on a word boundary and when xbitpos == padding_correction | ||
| 256 | - (the first time through). */ | ||
| 257 | - if (xbitpos % BITS_PER_WORD == 0 | ||
| 258 | - || xbitpos == padding_correction) | ||
| 259 | - { | ||
| 260 | - /* Generate an appropriate register. */ | ||
| 261 | - dst = gen_reg_rtx (word_mode); | ||
| 262 | - result_pseudos[xbitpos / BITS_PER_WORD] = dst; | ||
| 263 | - | ||
| 264 | - /* Clear the destination before we move anything into it. */ | ||
| 265 | - emit_move_insn (dst, CONST0_RTX (GET_MODE (dst))); | ||
| 266 | - } | ||
| 267 | - | ||
| 268 | - /* We need a new source operand each time bitpos is on a word | ||
| 269 | - boundary. */ | ||
| 270 | - if (bitpos % BITS_PER_WORD == 0) | ||
| 271 | - src = operand_subword_force (result_val, | ||
| 272 | - bitpos / BITS_PER_WORD, | ||
| 273 | - BLKmode); | ||
| 274 | - | ||
| 275 | - /* Use bitpos for the source extraction (left justified) and | ||
| 276 | - xbitpos for the destination store (right justified). */ | ||
| 277 | - store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode, | ||
| 278 | - extract_bit_field (src, bitsize, | ||
| 279 | - bitpos % BITS_PER_WORD, 1, false, | ||
| 280 | - NULL_RTX, word_mode, word_mode)); | ||
| 281 | - } | ||
| 282 | - | ||
| 283 | - tmpmode = GET_MODE (result_rtl); | ||
| 284 | - if (tmpmode == BLKmode) | ||
| 285 | - { | ||
| 286 | - /* Find the smallest integer mode large enough to hold the | ||
| 287 | - entire structure and use that mode instead of BLKmode | ||
| 288 | - on the USE insn for the return register. */ | ||
| 289 | - for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT); | ||
| 290 | - tmpmode != VOIDmode; | ||
| 291 | - tmpmode = GET_MODE_WIDER_MODE (tmpmode)) | ||
| 292 | - /* Have we found a large enough mode? */ | ||
| 293 | - if (GET_MODE_SIZE (tmpmode) >= bytes) | ||
| 294 | - break; | ||
| 295 | - | ||
| 296 | - /* A suitable mode should have been found. */ | ||
| 297 | - gcc_assert (tmpmode != VOIDmode); | ||
| 298 | - | ||
| 299 | - PUT_MODE (result_rtl, tmpmode); | ||
| 300 | - } | ||
| 301 | - | ||
| 302 | - if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode)) | ||
| 303 | - result_reg_mode = word_mode; | ||
| 304 | + val = copy_blkmode_to_reg (GET_MODE (result_rtl), retval_rhs); | ||
| 305 | + if (val) | ||
| 306 | + { | ||
| 307 | + /* Use the mode of the result value on the return register. */ | ||
| 308 | + PUT_MODE (result_rtl, GET_MODE (val)); | ||
| 309 | + expand_value_return (val); | ||
| 310 | + } | ||
| 311 | else | ||
| 312 | - result_reg_mode = tmpmode; | ||
| 313 | - result_reg = gen_reg_rtx (result_reg_mode); | ||
| 314 | - | ||
| 315 | - for (i = 0; i < n_regs; i++) | ||
| 316 | - emit_move_insn (operand_subword (result_reg, i, 0, result_reg_mode), | ||
| 317 | - result_pseudos[i]); | ||
| 318 | - | ||
| 319 | - if (tmpmode != result_reg_mode) | ||
| 320 | - result_reg = gen_lowpart (tmpmode, result_reg); | ||
| 321 | - | ||
| 322 | - expand_value_return (result_reg); | ||
| 323 | + expand_null_return (); | ||
| 324 | } | ||
| 325 | else if (retval_rhs != 0 | ||
| 326 | && !VOID_TYPE_P (TREE_TYPE (retval_rhs)) | ||
| 327 | |||
| 328 | === added file 'gcc/testsuite/g++.dg/pr48660.C' | ||
| 329 | --- old/gcc/testsuite/g++.dg/pr48660.C 1970-01-01 00:00:00 +0000 | ||
| 330 | +++ new/gcc/testsuite/g++.dg/pr48660.C 2011-10-12 08:01:43 +0000 | ||
| 331 | @@ -0,0 +1,22 @@ | ||
| 332 | +template<int N> struct val { char a[N]; }; | ||
| 333 | + | ||
| 334 | +class Base | ||
| 335 | +{ | ||
| 336 | +public: | ||
| 337 | + virtual val<1> get1() const = 0; | ||
| 338 | + virtual val<2> get2() const = 0; | ||
| 339 | + virtual val<3> get3() const = 0; | ||
| 340 | + virtual val<4> get4() const = 0; | ||
| 341 | +}; | ||
| 342 | + | ||
| 343 | +class Derived : public virtual Base | ||
| 344 | +{ | ||
| 345 | +public: | ||
| 346 | + virtual val<1> get1() const { return foo->get1(); } | ||
| 347 | + virtual val<2> get2() const { return foo->get2(); } | ||
| 348 | + virtual val<3> get3() const { return foo->get3(); } | ||
| 349 | + virtual val<4> get4() const { return foo->get4(); } | ||
| 350 | + Base *foo; | ||
| 351 | +}; | ||
| 352 | + | ||
| 353 | +Base* make() { return new Derived; } | ||
| 354 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106860.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106860.patch new file mode 100644 index 0000000000..895d6a6cff --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106860.patch | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | 2012-01-12 Ulrich Weigand <ulrich.weigand@linaro.org> | ||
| 2 | |||
| 3 | LP 879725 | ||
| 4 | Backport from mainline: | ||
| 5 | |||
| 6 | 2012-01-02 Revital Eres <revital.eres@linaro.org> | ||
| 7 | |||
| 8 | gcc/ | ||
| 9 | * ddg.c (def_has_ccmode_p): New function. | ||
| 10 | (add_cross_iteration_register_deps, | ||
| 11 | create_ddg_dep_from_intra_loop_link): Call it. | ||
| 12 | |||
| 13 | gcc/testsuite/ | ||
| 14 | * gcc.dg/sms-11.c: New file. | ||
| 15 | |||
| 16 | === modified file 'gcc/ddg.c' | ||
| 17 | --- old/gcc/ddg.c 2011-10-02 06:56:53 +0000 | ||
| 18 | +++ new/gcc/ddg.c 2012-01-10 16:05:14 +0000 | ||
| 19 | @@ -166,6 +166,24 @@ | ||
| 20 | return false; | ||
| 21 | } | ||
| 22 | |||
| 23 | +/* Return true if one of the definitions in INSN has MODE_CC. Otherwise | ||
| 24 | + return false. */ | ||
| 25 | +static bool | ||
| 26 | +def_has_ccmode_p (rtx insn) | ||
| 27 | +{ | ||
| 28 | + df_ref *def; | ||
| 29 | + | ||
| 30 | + for (def = DF_INSN_DEFS (insn); *def; def++) | ||
| 31 | + { | ||
| 32 | + enum machine_mode mode = GET_MODE (DF_REF_REG (*def)); | ||
| 33 | + | ||
| 34 | + if (GET_MODE_CLASS (mode) == MODE_CC) | ||
| 35 | + return true; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + return false; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | /* Computes the dependence parameters (latency, distance etc.), creates | ||
| 42 | a ddg_edge and adds it to the given DDG. */ | ||
| 43 | static void | ||
| 44 | @@ -202,6 +220,7 @@ | ||
| 45 | whose register has multiple defs in the loop. */ | ||
| 46 | if (flag_modulo_sched_allow_regmoves | ||
| 47 | && (t == ANTI_DEP && dt == REG_DEP) | ||
| 48 | + && !def_has_ccmode_p (dest_node->insn) | ||
| 49 | && !autoinc_var_is_used_p (dest_node->insn, src_node->insn)) | ||
| 50 | { | ||
| 51 | rtx set; | ||
| 52 | @@ -335,7 +354,8 @@ | ||
| 53 | if (DF_REF_ID (last_def) != DF_REF_ID (first_def) | ||
| 54 | || !flag_modulo_sched_allow_regmoves | ||
| 55 | || JUMP_P (use_node->insn) | ||
| 56 | - || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)) | ||
| 57 | + || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn) | ||
| 58 | + || def_has_ccmode_p (DF_REF_INSN (last_def))) | ||
| 59 | create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP, | ||
| 60 | REG_DEP, 1); | ||
| 61 | |||
| 62 | |||
| 63 | === added file 'gcc/testsuite/gcc.dg/sms-11.c' | ||
| 64 | --- old/gcc/testsuite/gcc.dg/sms-11.c 1970-01-01 00:00:00 +0000 | ||
| 65 | +++ new/gcc/testsuite/gcc.dg/sms-11.c 2012-01-10 16:05:14 +0000 | ||
| 66 | @@ -0,0 +1,37 @@ | ||
| 67 | +/* { dg-do run } */ | ||
| 68 | +/* { dg-options "-O2 -fmodulo-sched -fmodulo-sched-allow-regmoves -fdump-rtl-sms" } */ | ||
| 69 | + | ||
| 70 | +extern void abort (void); | ||
| 71 | + | ||
| 72 | +float out[4][4] = { 6, 6, 7, 5, 6, 7, 5, 5, 6, 4, 4, 4, 6, 2, 3, 4 }; | ||
| 73 | + | ||
| 74 | +void | ||
| 75 | +invert (void) | ||
| 76 | +{ | ||
| 77 | + int i, j, k = 0, swap; | ||
| 78 | + float tmp[4][4] = { 5, 6, 7, 5, 6, 7, 5, 5, 4, 4, 4, 4, 3, 2, 3, 4 }; | ||
| 79 | + | ||
| 80 | + for (i = 0; i < 4; i++) | ||
| 81 | + { | ||
| 82 | + for (j = i + 1; j < 4; j++) | ||
| 83 | + if (tmp[j][i] > tmp[i][i]) | ||
| 84 | + swap = j; | ||
| 85 | + | ||
| 86 | + if (swap != i) | ||
| 87 | + tmp[i][k] = tmp[swap][k]; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + for (i = 0; i < 4; i++) | ||
| 91 | + for (j = 0; j < 4; j++) | ||
| 92 | + if (tmp[i][j] != out[i][j]) | ||
| 93 | + abort (); | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +int | ||
| 97 | +main () | ||
| 98 | +{ | ||
| 99 | + invert (); | ||
| 100 | + return 0; | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +/* { dg-final { cleanup-rtl-dump "sms" } } */ | ||
| 104 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106861.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106861.patch new file mode 100644 index 0000000000..0199f7b89b --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106861.patch | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | 2012-01-18 Michael Hope <michael.hope@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline r183126: | ||
| 4 | |||
| 5 | 2012-01-12 Ira Rosen <irar@il.ibm.com> | ||
| 6 | |||
| 7 | gcc/ | ||
| 8 | PR tree-optimization/51799 | ||
| 9 | * tree-vect-patterns.c (vect_recog_over_widening_pattern): Check | ||
| 10 | that the last operation is a type demotion. | ||
| 11 | |||
| 12 | gcc/testsuite/ | ||
| 13 | * gcc.dg/vect/pr51799.c: New test. | ||
| 14 | * gcc.dg/vect/vect-widen-shift-u8.c: Expect two widening shift | ||
| 15 | patterns. | ||
| 16 | |||
| 17 | === added file 'gcc/testsuite/gcc.dg/vect/pr51799.c' | ||
| 18 | --- old/gcc/testsuite/gcc.dg/vect/pr51799.c 1970-01-01 00:00:00 +0000 | ||
| 19 | +++ new/gcc/testsuite/gcc.dg/vect/pr51799.c 2012-01-18 01:53:19 +0000 | ||
| 20 | @@ -0,0 +1,18 @@ | ||
| 21 | +/* { dg-do compile } */ | ||
| 22 | + | ||
| 23 | +typedef signed char int8_t; | ||
| 24 | +typedef unsigned char uint8_t; | ||
| 25 | +typedef signed short int16_t; | ||
| 26 | +typedef unsigned long uint32_t; | ||
| 27 | +void | ||
| 28 | +f0a (uint32_t * __restrict__ result, int8_t * __restrict__ arg1, | ||
| 29 | + uint32_t * __restrict__ arg4, int8_t temp_6) | ||
| 30 | +{ | ||
| 31 | + int idx; | ||
| 32 | + for (idx = 0; idx < 416; idx += 1) | ||
| 33 | + { | ||
| 34 | + result[idx] = (uint8_t)(((arg1[idx] << 7) + arg4[idx]) * temp_6); | ||
| 35 | + } | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +/* { dg-final { cleanup-tree-dump "vect" } } */ | ||
| 39 | |||
| 40 | === modified file 'gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c' | ||
| 41 | --- old/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c 2011-10-23 13:33:07 +0000 | ||
| 42 | +++ new/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c 2012-01-18 01:53:19 +0000 | ||
| 43 | @@ -59,7 +59,6 @@ | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | -/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */ | ||
| 48 | +/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */ | ||
| 49 | /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ | ||
| 50 | /* { dg-final { cleanup-tree-dump "vect" } } */ | ||
| 51 | - | ||
| 52 | |||
| 53 | === modified file 'gcc/tree-vect-patterns.c' | ||
| 54 | --- old/gcc/tree-vect-patterns.c 2011-12-20 07:47:44 +0000 | ||
| 55 | +++ new/gcc/tree-vect-patterns.c 2012-01-18 01:53:19 +0000 | ||
| 56 | @@ -1224,13 +1224,15 @@ | ||
| 57 | { | ||
| 58 | use_lhs = gimple_assign_lhs (use_stmt); | ||
| 59 | use_type = TREE_TYPE (use_lhs); | ||
| 60 | - /* Support only type promotion or signedess change. Check that USE_TYPE | ||
| 61 | - is not bigger than the original type. */ | ||
| 62 | + /* Support only type demotion or signedess change. */ | ||
| 63 | if (!INTEGRAL_TYPE_P (use_type) | ||
| 64 | - || TYPE_PRECISION (new_type) > TYPE_PRECISION (use_type) | ||
| 65 | - || TYPE_PRECISION (type) < TYPE_PRECISION (use_type)) | ||
| 66 | + || TYPE_PRECISION (type) <= TYPE_PRECISION (use_type)) | ||
| 67 | return NULL; | ||
| 68 | |||
| 69 | + /* Check that NEW_TYPE is not bigger than the conversion result. */ | ||
| 70 | + if (TYPE_PRECISION (new_type) > TYPE_PRECISION (use_type)) | ||
| 71 | + return NULL; | ||
| 72 | + | ||
| 73 | if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type) | ||
| 74 | || TYPE_PRECISION (new_type) != TYPE_PRECISION (use_type)) | ||
| 75 | { | ||
| 76 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106862.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106862.patch new file mode 100644 index 0000000000..a20d889a56 --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106862.patch | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | 2012-01-16 Michael Hope <michael.hope@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline r183011: | ||
| 4 | |||
| 5 | 2012-01-09 Matthew Gretton-Dann <matthew.gretton-dann@arm.com> | ||
| 6 | |||
| 7 | * config/arm/arm-cores.def (cortex-a15): Use cortex_a15_tune for | ||
| 8 | tuning parameters. | ||
| 9 | * config/arm/arm.c (arm_cortex_a15_tune): New static variable. | ||
| 10 | |||
| 11 | === modified file 'gcc/config/arm/arm-cores.def' | ||
| 12 | --- old/gcc/config/arm/arm-cores.def 2011-10-19 16:46:51 +0000 | ||
| 13 | +++ new/gcc/config/arm/arm-cores.def 2012-01-15 22:02:31 +0000 | ||
| 14 | @@ -128,7 +128,7 @@ | ||
| 15 | ARM_CORE("cortex-a5", cortexa5, 7A, FL_LDSCHED, cortex_a5) | ||
| 16 | ARM_CORE("cortex-a8", cortexa8, 7A, FL_LDSCHED, cortex) | ||
| 17 | ARM_CORE("cortex-a9", cortexa9, 7A, FL_LDSCHED, cortex_a9) | ||
| 18 | -ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex) | ||
| 19 | +ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) | ||
| 20 | ARM_CORE("cortex-r4", cortexr4, 7R, FL_LDSCHED, cortex) | ||
| 21 | ARM_CORE("cortex-r4f", cortexr4f, 7R, FL_LDSCHED, cortex) | ||
| 22 | ARM_CORE("cortex-r5", cortexr5, 7R, FL_LDSCHED | FL_ARM_DIV, cortex) | ||
| 23 | |||
| 24 | === modified file 'gcc/config/arm/arm.c' | ||
| 25 | --- old/gcc/config/arm/arm.c 2012-01-05 15:35:39 +0000 | ||
| 26 | +++ new/gcc/config/arm/arm.c 2012-01-15 22:02:31 +0000 | ||
| 27 | @@ -983,6 +983,17 @@ | ||
| 28 | arm_default_branch_cost | ||
| 29 | }; | ||
| 30 | |||
| 31 | +const struct tune_params arm_cortex_a15_tune = | ||
| 32 | +{ | ||
| 33 | + arm_9e_rtx_costs, | ||
| 34 | + NULL, | ||
| 35 | + 1, /* Constant limit. */ | ||
| 36 | + 1, /* Max cond insns. */ | ||
| 37 | + ARM_PREFETCH_NOT_BENEFICIAL, /* TODO: Calculate correct values. */ | ||
| 38 | + false, /* Prefer constant pool. */ | ||
| 39 | + arm_cortex_a5_branch_cost | ||
| 40 | +}; | ||
| 41 | + | ||
| 42 | const struct tune_params arm_fa726te_tune = | ||
| 43 | { | ||
| 44 | arm_9e_rtx_costs, | ||
| 45 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106863.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106863.patch new file mode 100644 index 0000000000..e93493f17f --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106863.patch | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | 2012-01-16 Michael Hope <michael.hope@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline r182561: | ||
| 4 | |||
| 5 | 2011-12-20 Richard Henderson <rth@redhat.com> | ||
| 6 | |||
| 7 | gcc/ | ||
| 8 | * config/arm/arm.md (*arm_cmpdi_unsigned): Enable for thumb2. | ||
| 9 | * config/arm/arm.c (arm_select_cc_mode): Use it. | ||
| 10 | |||
| 11 | === modified file 'gcc/config/arm/arm.c' | ||
| 12 | --- old/gcc/config/arm/arm.c 2012-01-15 22:02:31 +0000 | ||
| 13 | +++ new/gcc/config/arm/arm.c 2012-01-23 00:06:27 +0000 | ||
| 14 | @@ -11602,7 +11602,7 @@ | ||
| 15 | return CC_Zmode; | ||
| 16 | |||
| 17 | /* We can do an equality test in three Thumb instructions. */ | ||
| 18 | - if (!TARGET_ARM) | ||
| 19 | + if (!TARGET_32BIT) | ||
| 20 | return CC_Zmode; | ||
| 21 | |||
| 22 | /* FALLTHROUGH */ | ||
| 23 | @@ -11614,7 +11614,7 @@ | ||
| 24 | /* DImode unsigned comparisons can be implemented by cmp + | ||
| 25 | cmpeq without a scratch register. Not worth doing in | ||
| 26 | Thumb-2. */ | ||
| 27 | - if (TARGET_ARM) | ||
| 28 | + if (TARGET_32BIT) | ||
| 29 | return CC_CZmode; | ||
| 30 | |||
| 31 | /* FALLTHROUGH */ | ||
| 32 | |||
| 33 | === modified file 'gcc/config/arm/arm.md' | ||
| 34 | --- old/gcc/config/arm/arm.md 2012-01-05 15:35:39 +0000 | ||
| 35 | +++ new/gcc/config/arm/arm.md 2012-01-15 21:02:00 +0000 | ||
| 36 | @@ -7515,8 +7515,8 @@ | ||
| 37 | [(set (reg:CC_CZ CC_REGNUM) | ||
| 38 | (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r") | ||
| 39 | (match_operand:DI 1 "arm_di_operand" "rDi")))] | ||
| 40 | - "TARGET_ARM" | ||
| 41 | - "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1" | ||
| 42 | + "TARGET_32BIT" | ||
| 43 | + "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1" | ||
| 44 | [(set_attr "conds" "set") | ||
| 45 | (set_attr "length" "8")] | ||
| 46 | ) | ||
| 47 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106864.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106864.patch new file mode 100644 index 0000000000..f15f37a583 --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106864.patch | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | 2012-01-16 Michael Hope <michael.hope@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline r181210: | ||
| 4 | |||
| 5 | gcc/ | ||
| 6 | 2011-11-07 Matthew Gretton-Dann <matthew.gretton-dann@arm.com> | ||
| 7 | |||
| 8 | * config/arm/arm-cores.def: Add -mcpu=cortex-a7. | ||
| 9 | * config/arm/arm-tables.opt: Regenerate. | ||
| 10 | * config/arm/arm-tune.md: Likewise. | ||
| 11 | * config/arm/bpabi.h (BE8_LINK_SPEC): Add Cortex A-7. | ||
| 12 | * doc/invoke.texi: Document -mcpu=cortex-a7. | ||
| 13 | |||
| 14 | === modified file 'gcc/config/arm/arm-cores.def' | ||
| 15 | --- old/gcc/config/arm/arm-cores.def 2012-01-15 22:02:31 +0000 | ||
| 16 | +++ new/gcc/config/arm/arm-cores.def 2012-01-23 00:36:02 +0000 | ||
| 17 | @@ -126,6 +126,7 @@ | ||
| 18 | ARM_CORE("arm1156t2f-s", arm1156t2fs, 6T2, FL_LDSCHED | FL_VFPV2, v6t2) | ||
| 19 | ARM_CORE("generic-armv7-a", genericv7a, 7A, FL_LDSCHED, cortex) | ||
| 20 | ARM_CORE("cortex-a5", cortexa5, 7A, FL_LDSCHED, cortex_a5) | ||
| 21 | +ARM_CORE("cortex-a7", cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex) | ||
| 22 | ARM_CORE("cortex-a8", cortexa8, 7A, FL_LDSCHED, cortex) | ||
| 23 | ARM_CORE("cortex-a9", cortexa9, 7A, FL_LDSCHED, cortex_a9) | ||
| 24 | ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) | ||
| 25 | |||
| 26 | === modified file 'gcc/config/arm/arm-tune.md' | ||
| 27 | --- old/gcc/config/arm/arm-tune.md 2011-10-19 16:46:51 +0000 | ||
| 28 | +++ new/gcc/config/arm/arm-tune.md 2012-01-15 22:43:29 +0000 | ||
| 29 | @@ -1,5 +1,5 @@ | ||
| 30 | ;; -*- buffer-read-only: t -*- | ||
| 31 | ;; Generated automatically by gentune.sh from arm-cores.def | ||
| 32 | (define_attr "tune" | ||
| 33 | - "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,fa526,fa626,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,arm1156t2fs,genericv7a,cortexa5,cortexa8,cortexa9,cortexa15,cortexr4,cortexr4f,cortexr5,cortexm4,cortexm3,cortexm1,cortexm0" | ||
| 34 | + "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,fa526,fa626,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,arm1156t2fs,genericv7a,cortexa5,cortexa7,cortexa8,cortexa9,cortexa15,cortexr4,cortexr4f,cortexr5,cortexm4,cortexm3,cortexm1,cortexm0" | ||
| 35 | (const (symbol_ref "((enum attr_tune) arm_tune)"))) | ||
| 36 | |||
| 37 | === modified file 'gcc/config/arm/bpabi.h' | ||
| 38 | --- old/gcc/config/arm/bpabi.h 2011-11-02 21:02:53 +0000 | ||
| 39 | +++ new/gcc/config/arm/bpabi.h 2012-01-15 22:43:29 +0000 | ||
| 40 | @@ -56,6 +56,7 @@ | ||
| 41 | "|march=armv4|mcpu=fa526|mcpu=fa626:--fix-v4bx}" | ||
| 42 | |||
| 43 | #define BE8_LINK_SPEC " %{mbig-endian:%{march=armv7-a|mcpu=cortex-a5"\ | ||
| 44 | + "|mcpu=cortex-a7"\ | ||
| 45 | "|mcpu=cortex-a8|mcpu=cortex-a9|mcpu=cortex-a15|mcpu=generic-armv7-a"\ | ||
| 46 | ":%{!r:--be8}}}" | ||
| 47 | |||
| 48 | |||
| 49 | === modified file 'gcc/doc/invoke.texi' | ||
| 50 | --- old/gcc/doc/invoke.texi 2012-01-05 15:35:39 +0000 | ||
| 51 | +++ new/gcc/doc/invoke.texi 2012-01-15 22:43:29 +0000 | ||
| 52 | @@ -10202,8 +10202,8 @@ | ||
| 53 | @samp{arm10e}, @samp{arm1020e}, @samp{arm1022e}, | ||
| 54 | @samp{arm1136j-s}, @samp{arm1136jf-s}, @samp{mpcore}, @samp{mpcorenovfp}, | ||
| 55 | @samp{arm1156t2-s}, @samp{arm1156t2f-s}, @samp{arm1176jz-s}, @samp{arm1176jzf-s}, | ||
| 56 | -@samp{cortex-a5}, @samp{cortex-a8}, @samp{cortex-a9}, @samp{cortex-a15}, | ||
| 57 | -@samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-r5}, | ||
| 58 | +@samp{cortex-a5}, @samp{cortex-a7}, @samp{cortex-a8}, @samp{cortex-a9}, | ||
| 59 | +@samp{cortex-a15}, @samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-r5}, | ||
| 60 | @samp{cortex-m4}, @samp{cortex-m3}, | ||
| 61 | @samp{cortex-m1}, | ||
| 62 | @samp{cortex-m0}, | ||
| 63 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106865.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106865.patch new file mode 100644 index 0000000000..5b0735b004 --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106865.patch | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | 2012-01-20 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline | ||
| 4 | 2012-01-20 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 5 | |||
| 6 | PR target/51819 | ||
| 7 | * config/arm/arm.c (arm_print_operand): Correct output of alignment | ||
| 8 | hints for neon loads and stores. | ||
| 9 | |||
| 10 | === modified file 'gcc/config/arm/arm.c' | ||
| 11 | --- old/gcc/config/arm/arm.c 2012-01-23 00:06:27 +0000 | ||
| 12 | +++ new/gcc/config/arm/arm.c 2012-01-23 18:54:21 +0000 | ||
| 13 | @@ -17463,9 +17463,9 @@ | ||
| 14 | /* Only certain alignment specifiers are supported by the hardware. */ | ||
| 15 | if (memsize == 16 && (align % 32) == 0) | ||
| 16 | align_bits = 256; | ||
| 17 | - else if ((memsize == 8 || memsize == 16) && (align % 16) == 0) | ||
| 18 | + else if (memsize == 16 && (align % 16) == 0) | ||
| 19 | align_bits = 128; | ||
| 20 | - else if ((align % 8) == 0) | ||
| 21 | + else if (memsize >= 8 && (align % 8) == 0) | ||
| 22 | align_bits = 64; | ||
| 23 | else | ||
| 24 | align_bits = 0; | ||
| 25 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch new file mode 100644 index 0000000000..de3d2ff4cf --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch | |||
| @@ -0,0 +1,2389 @@ | |||
| 1 | 2012-02-08 Ulrich Weigand <ulrich.weigand@linaro.org> | ||
| 2 | |||
| 3 | gcc/ | ||
| 4 | * config/arm/arm.c (arm_option_optimization_table): Enable | ||
| 5 | -fsched-pressure using -fsched-pressure-algorithm=model by | ||
| 6 | default when optimizing. | ||
| 7 | |||
| 8 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 9 | |||
| 10 | gcc/ | ||
| 11 | * sched-deps.c (fixup_sched_groups): Rename to... | ||
| 12 | (chain_to_prev_insn): ...this. | ||
| 13 | (chain_to_prev_insn_p): New function. | ||
| 14 | (deps_analyze_insn): Use it instead of SCHED_GROUP_P. | ||
| 15 | |||
| 16 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 17 | |||
| 18 | gcc/ | ||
| 19 | * sched-int.h (_haifa_insn_data): Move priority_status. | ||
| 20 | Add model_index. | ||
| 21 | (INSN_MODEL_INDEX): New macro. | ||
| 22 | * haifa-sched.c (insn_delay): New function. | ||
| 23 | (sched_regno_pressure_class): Update commentary. | ||
| 24 | (mark_regno_birth_or_death): Pass the liveness bitmap and | ||
| 25 | pressure array as arguments, instead of using curr_reg_live and | ||
| 26 | curr_reg_pressure. Only update the pressure if the bit in the | ||
| 27 | liveness set has changed. | ||
| 28 | (initiate_reg_pressure_info): Always trust the live-in set for | ||
| 29 | SCHED_PRESSURE_MODEL. | ||
| 30 | (initiate_bb_reg_pressure_info): Update call to | ||
| 31 | mark_regno_birth_or_death. | ||
| 32 | (dep_list_size): Take the list as argument. | ||
| 33 | (calculate_reg_deaths): New function, extracted from... | ||
| 34 | (setup_insn_reg_pressure_info): ...here. | ||
| 35 | (MODEL_BAR): New macro. | ||
| 36 | (model_pressure_data, model_insn_info, model_pressure_limit) | ||
| 37 | (model_pressure_group): New structures. | ||
| 38 | (model_schedule, model_worklist, model_insns, model_num_insns) | ||
| 39 | (model_curr_point, model_before_pressure, model_next_priority): | ||
| 40 | New variables. | ||
| 41 | (MODEL_PRESSURE_DATA, MODEL_MAX_PRESSURE, MODEL_REF_PRESSURE) | ||
| 42 | (MODEL_INSN_INFO, MODEL_INSN): New macros. | ||
| 43 | (model_index, model_update_limit_points_in_group): New functions. | ||
| 44 | (model_update_limit_points, model_last_use_except): Likewise. | ||
| 45 | (model_start_update_pressure, model_update_pressure): Likewise. | ||
| 46 | (model_recompute, model_spill_cost, model_excess_group_cost): Likewise. | ||
| 47 | (model_excess_cost, model_dump_pressure_points): Likewise. | ||
| 48 | (model_set_excess_costs): Likewise. | ||
| 49 | (rank_for_schedule): Extend SCHED_PRIORITY_WEIGHTED ordering to | ||
| 50 | SCHED_PRIORITY_MODEL. Use insn_delay. Use the order in the model | ||
| 51 | schedule as an alternative tie-breaker. Update the call to | ||
| 52 | dep_list_size. | ||
| 53 | (ready_sort): Call model_set_excess_costs. | ||
| 54 | (update_register_pressure): Update call to mark_regno_birth_or_death. | ||
| 55 | Rely on that function to check liveness rather than doing it here. | ||
| 56 | (model_classify_pressure, model_order_p, model_add_to_worklist_at) | ||
| 57 | (model_remove_from_worklist, model_add_to_worklist, model_promote_insn) | ||
| 58 | (model_add_to_schedule, model_analyze_insns, model_init_pressure_group) | ||
| 59 | (model_record_pressure, model_record_pressures): New functions. | ||
| 60 | (model_record_final_pressures, model_add_successors_to_worklist) | ||
| 61 | (model_promote_predecessors, model_choose_insn): Likewise. | ||
| 62 | (model_reset_queue_indices, model_dump_pressure_summary): Likewise. | ||
| 63 | (model_start_schedule, model_finalize_pressure_group): Likewise. | ||
| 64 | (model_end_schedule): Likewise. | ||
| 65 | (schedule_insn): Say when we're scheduling the next instruction | ||
| 66 | in the model schedule. | ||
| 67 | (schedule_insn): Handle SCHED_PRESSURE_MODEL. | ||
| 68 | (queue_to_ready): Do not add instructions that are | ||
| 69 | MAX_SCHED_READY_INSNS beyond the current point of the model schedule. | ||
| 70 | Always allow the next instruction in the model schedule to be added. | ||
| 71 | (debug_ready_list): Print the INSN_REG_PRESSURE_EXCESS_COST_CHANGE | ||
| 72 | and delay for SCHED_PRESSURE_MODEL too. | ||
| 73 | (prune_ready_list): Extend SCHED_PRIORITY_WEIGHTED handling to | ||
| 74 | SCHED_PRIORITY_MODEL, but also take the DFA into account. | ||
| 75 | (schedule_block): Call model_start_schedule and model_end_schedule. | ||
| 76 | Extend SCHED_PRIORITY_WEIGHTED stall handling to SCHED_PRIORITY_MODEL. | ||
| 77 | (sched_init): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE handling | ||
| 78 | to SCHED_PRESSURE_MODEL, but don't allocate saved_reg_live or | ||
| 79 | region_ref_regs. | ||
| 80 | (sched_finish): Update accordingly. | ||
| 81 | (fix_tick_ready): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE handling | ||
| 82 | to SCHED_PRESSURE_MODEL. | ||
| 83 | (add_jump_dependencies): Update call to dep_list_size. | ||
| 84 | (haifa_finish_h_i_d): Fix leak of max_reg_pressure. | ||
| 85 | (haifa_init_insn): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE handling | ||
| 86 | to SCHED_PRESSURE_MODEL. | ||
| 87 | * sched-deps.c (init_insn_reg_pressure_info): Likewise, but don't | ||
| 88 | allocate INSN_MAX_REG_PRESSURE for SCHED_PRESSURE_MODEL. | ||
| 89 | (sched_analyze_insn): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE | ||
| 90 | handling to SCHED_PRESSURE_MODEL. | ||
| 91 | |||
| 92 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 93 | |||
| 94 | gcc/ | ||
| 95 | * common.opt (fsched-pressure-algorithm=): New option. | ||
| 96 | * flag-types.h (sched_pressure_algorithm): New enum. | ||
| 97 | * sched-int.h (sched_pressure_p): Replace with... | ||
| 98 | (sched_pressure): ...this new variable. | ||
| 99 | * haifa-sched.c (sched_pressure_p): Replace with... | ||
| 100 | (sched_pressure): ...this new variable. | ||
| 101 | (sched_regno_pressure_class, rank_for_schedule, ready_sort) | ||
| 102 | (update_reg_and_insn_max_reg_pressure, schedule_insn) | ||
| 103 | (debug_ready_list, schedule_block, sched_init, sched_finish) | ||
| 104 | (fix_tick_ready, haifa_init_insn): Update accordingly. | ||
| 105 | * sched-deps.c (init_insn_reg_pressure_info): Likewise. | ||
| 106 | * sched-rgn.c (schedule_region): Likewise. | ||
| 107 | |||
| 108 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
| 109 | |||
| 110 | gcc/ | ||
| 111 | Backport from mainline: | ||
| 112 | |||
| 113 | 2011-04-01 Bernd Schmidt <bernds@codesourcery.com> | ||
| 114 | |||
| 115 | * haifa-sched.c (prune_ready_list): New function, broken out of | ||
| 116 | schedule_block. | ||
| 117 | (schedule_block): Use it. | ||
| 118 | |||
| 119 | === modified file 'gcc/common.opt' | ||
| 120 | --- old/gcc/common.opt 2011-04-11 15:26:47 +0000 | ||
| 121 | +++ new/gcc/common.opt 2012-02-08 23:38:13 +0000 | ||
| 122 | @@ -1614,6 +1614,19 @@ | ||
| 123 | Common Report Var(flag_sched_pressure) Init(0) Optimization | ||
| 124 | Enable register pressure sensitive insn scheduling | ||
| 125 | |||
| 126 | +fsched-pressure-algorithm= | ||
| 127 | +Common Joined RejectNegative Enum(sched_pressure_algorithm) Var(flag_sched_pressure_algorithm) Init(SCHED_PRESSURE_WEIGHTED) | ||
| 128 | +-fira-algorithm=[CB|priority] Set the used IRA algorithm | ||
| 129 | + | ||
| 130 | +Enum | ||
| 131 | +Name(sched_pressure_algorithm) Type(enum sched_pressure_algorithm) UnknownError(unknown %<fsched-pressure%> algorithm %qs) | ||
| 132 | + | ||
| 133 | +EnumValue | ||
| 134 | +Enum(sched_pressure_algorithm) String(weighted) Value(SCHED_PRESSURE_WEIGHTED) | ||
| 135 | + | ||
| 136 | +EnumValue | ||
| 137 | +Enum(sched_pressure_algorithm) String(model) Value(SCHED_PRESSURE_MODEL) | ||
| 138 | + | ||
| 139 | fsched-spec | ||
| 140 | Common Report Var(flag_schedule_speculative) Init(1) Optimization | ||
| 141 | Allow speculative motion of non-loads | ||
| 142 | |||
| 143 | === modified file 'gcc/config/arm/arm.c' | ||
| 144 | --- old/gcc/config/arm/arm.c 2012-02-01 14:13:07 +0000 | ||
| 145 | +++ new/gcc/config/arm/arm.c 2012-02-09 00:47:59 +0000 | ||
| 146 | @@ -311,6 +311,11 @@ | ||
| 147 | /* Set default optimization options. */ | ||
| 148 | static const struct default_options arm_option_optimization_table[] = | ||
| 149 | { | ||
| 150 | + /* Enable -fsched-pressure using -fsched-pressure-algorithm=model | ||
| 151 | + by default when optimizing. */ | ||
| 152 | + { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, | ||
| 153 | + { OPT_LEVELS_1_PLUS, OPT_fsched_pressure_algorithm_, | ||
| 154 | + NULL, SCHED_PRESSURE_MODEL }, | ||
| 155 | /* Enable section anchors by default at -O1 or higher. */ | ||
| 156 | { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, | ||
| 157 | { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | ||
| 158 | |||
| 159 | === modified file 'gcc/flag-types.h' | ||
| 160 | --- old/gcc/flag-types.h 2010-11-24 13:28:38 +0000 | ||
| 161 | +++ new/gcc/flag-types.h 2012-02-08 23:38:13 +0000 | ||
| 162 | @@ -106,6 +106,14 @@ | ||
| 163 | }; | ||
| 164 | #endif | ||
| 165 | |||
| 166 | +/* The algorithm used to implement -fsched-pressure. */ | ||
| 167 | +enum sched_pressure_algorithm | ||
| 168 | +{ | ||
| 169 | + SCHED_PRESSURE_NONE, | ||
| 170 | + SCHED_PRESSURE_WEIGHTED, | ||
| 171 | + SCHED_PRESSURE_MODEL | ||
| 172 | +}; | ||
| 173 | + | ||
| 174 | /* The algorithm used for the integrated register allocator (IRA). */ | ||
| 175 | enum ira_algorithm | ||
| 176 | { | ||
| 177 | |||
| 178 | === modified file 'gcc/haifa-sched.c' | ||
| 179 | --- old/gcc/haifa-sched.c 2011-02-19 20:59:23 +0000 | ||
| 180 | +++ new/gcc/haifa-sched.c 2012-02-08 23:39:02 +0000 | ||
| 181 | @@ -348,6 +348,14 @@ | ||
| 182 | /* Create empty basic block after the specified block. */ | ||
| 183 | basic_block (* sched_create_empty_bb) (basic_block); | ||
| 184 | |||
| 185 | +/* Return the number of cycles until INSN is expected to be ready. | ||
| 186 | + Return zero if it already is. */ | ||
| 187 | +static int | ||
| 188 | +insn_delay (rtx insn) | ||
| 189 | +{ | ||
| 190 | + return MAX (INSN_TICK (insn) - clock_var, 0); | ||
| 191 | +} | ||
| 192 | + | ||
| 193 | static int | ||
| 194 | may_trap_exp (const_rtx x, int is_store) | ||
| 195 | { | ||
| 196 | @@ -571,10 +579,10 @@ | ||
| 197 | |||
| 198 | /* Do register pressure sensitive insn scheduling if the flag is set | ||
| 199 | up. */ | ||
| 200 | -bool sched_pressure_p; | ||
| 201 | +enum sched_pressure_algorithm sched_pressure; | ||
| 202 | |||
| 203 | /* Map regno -> its cover class. The map defined only when | ||
| 204 | - SCHED_PRESSURE_P is true. */ | ||
| 205 | + SCHED_PRESSURE != SCHED_PRESSURE_NONE. */ | ||
| 206 | enum reg_class *sched_regno_cover_class; | ||
| 207 | |||
| 208 | /* The current register pressure. Only elements corresponding cover | ||
| 209 | @@ -602,10 +610,12 @@ | ||
| 210 | bitmap_clear (region_ref_regs); | ||
| 211 | } | ||
| 212 | |||
| 213 | -/* Update current register pressure related info after birth (if | ||
| 214 | - BIRTH_P) or death of register REGNO. */ | ||
| 215 | -static void | ||
| 216 | -mark_regno_birth_or_death (int regno, bool birth_p) | ||
| 217 | +/* PRESSURE[CL] describes the pressure on register class CL. Update it | ||
| 218 | + for the birth (if BIRTH_P) or death (if !BIRTH_P) of register REGNO. | ||
| 219 | + LIVE tracks the set of live registers; if it is null, assume that | ||
| 220 | + every birth or death is genuine. */ | ||
| 221 | +static inline void | ||
| 222 | +mark_regno_birth_or_death (bitmap live, int *pressure, int regno, bool birth_p) | ||
| 223 | { | ||
| 224 | enum reg_class cover_class; | ||
| 225 | |||
| 226 | @@ -616,15 +626,17 @@ | ||
| 227 | { | ||
| 228 | if (birth_p) | ||
| 229 | { | ||
| 230 | - bitmap_set_bit (curr_reg_live, regno); | ||
| 231 | - curr_reg_pressure[cover_class] | ||
| 232 | - += ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)]; | ||
| 233 | + if (!live || bitmap_set_bit (live, regno)) | ||
| 234 | + pressure[cover_class] | ||
| 235 | + += (ira_reg_class_nregs | ||
| 236 | + [cover_class][PSEUDO_REGNO_MODE (regno)]); | ||
| 237 | } | ||
| 238 | else | ||
| 239 | { | ||
| 240 | - bitmap_clear_bit (curr_reg_live, regno); | ||
| 241 | - curr_reg_pressure[cover_class] | ||
| 242 | - -= ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)]; | ||
| 243 | + if (!live || bitmap_clear_bit (live, regno)) | ||
| 244 | + pressure[cover_class] | ||
| 245 | + -= (ira_reg_class_nregs | ||
| 246 | + [cover_class][PSEUDO_REGNO_MODE (regno)]); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | } | ||
| 250 | @@ -633,13 +645,13 @@ | ||
| 251 | { | ||
| 252 | if (birth_p) | ||
| 253 | { | ||
| 254 | - bitmap_set_bit (curr_reg_live, regno); | ||
| 255 | - curr_reg_pressure[cover_class]++; | ||
| 256 | + if (!live || bitmap_set_bit (live, regno)) | ||
| 257 | + pressure[cover_class]++; | ||
| 258 | } | ||
| 259 | else | ||
| 260 | { | ||
| 261 | - bitmap_clear_bit (curr_reg_live, regno); | ||
| 262 | - curr_reg_pressure[cover_class]--; | ||
| 263 | + if (!live || bitmap_clear_bit (live, regno)) | ||
| 264 | + pressure[cover_class]--; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | } | ||
| 268 | @@ -657,8 +669,10 @@ | ||
| 269 | curr_reg_pressure[ira_reg_class_cover[i]] = 0; | ||
| 270 | bitmap_clear (curr_reg_live); | ||
| 271 | EXECUTE_IF_SET_IN_BITMAP (live, 0, j, bi) | ||
| 272 | - if (current_nr_blocks == 1 || bitmap_bit_p (region_ref_regs, j)) | ||
| 273 | - mark_regno_birth_or_death (j, true); | ||
| 274 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
| 275 | + || current_nr_blocks == 1 | ||
| 276 | + || bitmap_bit_p (region_ref_regs, j)) | ||
| 277 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, j, true); | ||
| 278 | } | ||
| 279 | |||
| 280 | /* Mark registers in X as mentioned in the current region. */ | ||
| 281 | @@ -712,7 +726,8 @@ | ||
| 282 | if (regno == INVALID_REGNUM) | ||
| 283 | break; | ||
| 284 | if (! bitmap_bit_p (df_get_live_in (bb), regno)) | ||
| 285 | - mark_regno_birth_or_death (regno, true); | ||
| 286 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, | ||
| 287 | + regno, true); | ||
| 288 | } | ||
| 289 | #endif | ||
| 290 | } | ||
| 291 | @@ -956,19 +971,19 @@ | ||
| 292 | return true; | ||
| 293 | } | ||
| 294 | |||
| 295 | -/* Compute the number of nondebug forward deps of an insn. */ | ||
| 296 | +/* Compute the number of nondebug deps in list LIST for INSN. */ | ||
| 297 | |||
| 298 | static int | ||
| 299 | -dep_list_size (rtx insn) | ||
| 300 | +dep_list_size (rtx insn, sd_list_types_def list) | ||
| 301 | { | ||
| 302 | sd_iterator_def sd_it; | ||
| 303 | dep_t dep; | ||
| 304 | int dbgcount = 0, nodbgcount = 0; | ||
| 305 | |||
| 306 | if (!MAY_HAVE_DEBUG_INSNS) | ||
| 307 | - return sd_lists_size (insn, SD_LIST_FORW); | ||
| 308 | + return sd_lists_size (insn, list); | ||
| 309 | |||
| 310 | - FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep) | ||
| 311 | + FOR_EACH_DEP (insn, list, sd_it, dep) | ||
| 312 | { | ||
| 313 | if (DEBUG_INSN_P (DEP_CON (dep))) | ||
| 314 | dbgcount++; | ||
| 315 | @@ -976,7 +991,7 @@ | ||
| 316 | nodbgcount++; | ||
| 317 | } | ||
| 318 | |||
| 319 | - gcc_assert (dbgcount + nodbgcount == sd_lists_size (insn, SD_LIST_FORW)); | ||
| 320 | + gcc_assert (dbgcount + nodbgcount == sd_lists_size (insn, list)); | ||
| 321 | |||
| 322 | return nodbgcount; | ||
| 323 | } | ||
| 324 | @@ -995,7 +1010,7 @@ | ||
| 325 | { | ||
| 326 | int this_priority = -1; | ||
| 327 | |||
| 328 | - if (dep_list_size (insn) == 0) | ||
| 329 | + if (dep_list_size (insn, SD_LIST_FORW) == 0) | ||
| 330 | /* ??? We should set INSN_PRIORITY to insn_cost when and insn has | ||
| 331 | some forward deps but all of them are ignored by | ||
| 332 | contributes_to_priority hook. At the moment we set priority of | ||
| 333 | @@ -1091,6 +1106,22 @@ | ||
| 334 | qsort (READY, N_READY, sizeof (rtx), rank_for_schedule); } \ | ||
| 335 | while (0) | ||
| 336 | |||
| 337 | +/* For each cover class CL, set DEATH[CL] to the number of registers | ||
| 338 | + in that class that die in INSN. */ | ||
| 339 | + | ||
| 340 | +static void | ||
| 341 | +calculate_reg_deaths (rtx insn, int *death) | ||
| 342 | +{ | ||
| 343 | + int i; | ||
| 344 | + struct reg_use_data *use; | ||
| 345 | + | ||
| 346 | + for (i = 0; i < ira_reg_class_cover_size; i++) | ||
| 347 | + death[ira_reg_class_cover[i]] = 0; | ||
| 348 | + for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
| 349 | + if (dying_use_p (use)) | ||
| 350 | + mark_regno_birth_or_death (0, death, use->regno, true); | ||
| 351 | +} | ||
| 352 | + | ||
| 353 | /* Setup info about the current register pressure impact of scheduling | ||
| 354 | INSN at the current scheduling point. */ | ||
| 355 | static void | ||
| 356 | @@ -1102,23 +1133,12 @@ | ||
| 357 | enum reg_class cl; | ||
| 358 | struct reg_pressure_data *pressure_info; | ||
| 359 | int *max_reg_pressure; | ||
| 360 | - struct reg_use_data *use; | ||
| 361 | static int death[N_REG_CLASSES]; | ||
| 362 | |||
| 363 | gcc_checking_assert (!DEBUG_INSN_P (insn)); | ||
| 364 | |||
| 365 | excess_cost_change = 0; | ||
| 366 | - for (i = 0; i < ira_reg_class_cover_size; i++) | ||
| 367 | - death[ira_reg_class_cover[i]] = 0; | ||
| 368 | - for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
| 369 | - if (dying_use_p (use)) | ||
| 370 | - { | ||
| 371 | - cl = sched_regno_cover_class[use->regno]; | ||
| 372 | - if (use->regno < FIRST_PSEUDO_REGISTER) | ||
| 373 | - death[cl]++; | ||
| 374 | - else | ||
| 375 | - death[cl] += ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (use->regno)]; | ||
| 376 | - } | ||
| 377 | + calculate_reg_deaths (insn, death); | ||
| 378 | pressure_info = INSN_REG_PRESSURE (insn); | ||
| 379 | max_reg_pressure = INSN_MAX_REG_PRESSURE (insn); | ||
| 380 | gcc_assert (pressure_info != NULL && max_reg_pressure != NULL); | ||
| 381 | @@ -1139,7 +1159,765 @@ | ||
| 382 | } | ||
| 383 | INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insn) = excess_cost_change; | ||
| 384 | } | ||
| 385 | - | ||
| 386 | + | ||
| 387 | +/* This is the first page of code related to SCHED_PRESSURE_MODEL. | ||
| 388 | + It tries to make the scheduler take register pressure into account | ||
| 389 | + without introducing too many unnecessary stalls. It hooks into the | ||
| 390 | + main scheduling algorithm at several points: | ||
| 391 | + | ||
| 392 | + - Before scheduling starts, model_start_schedule constructs a | ||
| 393 | + "model schedule" for the current block. This model schedule is | ||
| 394 | + chosen solely to keep register pressure down. It does not take the | ||
| 395 | + target's pipeline or the original instruction order into account, | ||
| 396 | + except as a tie-breaker. It also doesn't work to a particular | ||
| 397 | + pressure limit. | ||
| 398 | + | ||
| 399 | + This model schedule gives us an idea of what pressure can be | ||
| 400 | + achieved for the block gives us an example of a schedule that | ||
| 401 | + keeps to that pressure. It also makes the final schedule less | ||
| 402 | + dependent on the original instruction order. This is important | ||
| 403 | + because the original order can either be "wide" (many values live | ||
| 404 | + at once, such as in user-scheduled code) or "narrow" (few values | ||
| 405 | + live at once, such as after loop unrolling, where several | ||
| 406 | + iterations are executed sequentially). | ||
| 407 | + | ||
| 408 | + We do not apply this model schedule to the rtx stream. We simply | ||
| 409 | + record it in model_schedule. We also compute the maximum pressure, | ||
| 410 | + MP, that was seen during this schedule. | ||
| 411 | + | ||
| 412 | + - Instructions are added to the ready queue even if they require | ||
| 413 | + a stall. The length of the stall is instead computed as: | ||
| 414 | + | ||
| 415 | + MAX (INSN_TICK (INSN) - clock_var, 0) | ||
| 416 | + | ||
| 417 | + (= insn_delay). This allows rank_for_schedule to choose between | ||
| 418 | + introducing a deliberate stall or increasing pressure. | ||
| 419 | + | ||
| 420 | + - Before sorting the ready queue, model_set_excess_costs assigns | ||
| 421 | + a pressure-based cost to each ready instruction in the queue. | ||
| 422 | + This is the instruction's INSN_REG_PRESSURE_EXCESS_COST_CHANGE | ||
| 423 | + (ECC for short) and is effectively measured in cycles. | ||
| 424 | + | ||
| 425 | + - rank_for_schedule ranks instructions based on: | ||
| 426 | + | ||
| 427 | + ECC (insn) + insn_delay (insn) | ||
| 428 | + | ||
| 429 | + then as: | ||
| 430 | + | ||
| 431 | + insn_delay (insn) | ||
| 432 | + | ||
| 433 | + So, for example, an instruction X1 with an ECC of 1 that can issue | ||
| 434 | + now will win over an instruction X0 with an ECC of zero that would | ||
| 435 | + introduce a stall of one cycle. However, an instruction X2 with an | ||
| 436 | + ECC of 2 that can issue now will lose to X0. | ||
| 437 | + | ||
| 438 | + - When an instruction is scheduled, model_recompute updates the model | ||
| 439 | + schedule with the new pressures (some of which might now exceed the | ||
| 440 | + original maximum pressure MP). model_update_limit_points then searches | ||
| 441 | + for the new point of maximum pressure, if not already known. */ | ||
| 442 | + | ||
| 443 | +/* Used to separate high-verbosity debug information for SCHED_PRESSURE_MODEL | ||
| 444 | + from surrounding debug information. */ | ||
| 445 | +#define MODEL_BAR \ | ||
| 446 | + ";;\t\t+------------------------------------------------------\n" | ||
| 447 | + | ||
| 448 | +/* Information about the pressure on a particular register class at a | ||
| 449 | + particular point of the model schedule. */ | ||
| 450 | +struct model_pressure_data { | ||
| 451 | + /* The pressure at this point of the model schedule, or -1 if the | ||
| 452 | + point is associated with an instruction that has already been | ||
| 453 | + scheduled. */ | ||
| 454 | + int ref_pressure; | ||
| 455 | + | ||
| 456 | + /* The maximum pressure during or after this point of the model schedule. */ | ||
| 457 | + int max_pressure; | ||
| 458 | +}; | ||
| 459 | + | ||
| 460 | +/* Per-instruction information that is used while building the model | ||
| 461 | + schedule. Here, "schedule" refers to the model schedule rather | ||
| 462 | + than the main schedule. */ | ||
| 463 | +struct model_insn_info { | ||
| 464 | + /* The instruction itself. */ | ||
| 465 | + rtx insn; | ||
| 466 | + | ||
| 467 | + /* If this instruction is in model_worklist, these fields link to the | ||
| 468 | + previous (higher-priority) and next (lower-priority) instructions | ||
| 469 | + in the list. */ | ||
| 470 | + struct model_insn_info *prev; | ||
| 471 | + struct model_insn_info *next; | ||
| 472 | + | ||
| 473 | + /* While constructing the schedule, QUEUE_INDEX describes whether an | ||
| 474 | + instruction has already been added to the schedule (QUEUE_SCHEDULED), | ||
| 475 | + is in model_worklist (QUEUE_READY), or neither (QUEUE_NOWHERE). | ||
| 476 | + old_queue records the value that QUEUE_INDEX had before scheduling | ||
| 477 | + started, so that we can restore it once the schedule is complete. */ | ||
| 478 | + int old_queue; | ||
| 479 | + | ||
| 480 | + /* The relative importance of an unscheduled instruction. Higher | ||
| 481 | + values indicate greater importance. */ | ||
| 482 | + unsigned int model_priority; | ||
| 483 | + | ||
| 484 | + /* The length of the longest path of satisfied true dependencies | ||
| 485 | + that leads to this instruction. */ | ||
| 486 | + unsigned int depth; | ||
| 487 | + | ||
| 488 | + /* The length of the longest path of dependencies of any kind | ||
| 489 | + that leads from this instruction. */ | ||
| 490 | + unsigned int alap; | ||
| 491 | + | ||
| 492 | + /* The number of predecessor nodes that must still be scheduled. */ | ||
| 493 | + int unscheduled_preds; | ||
| 494 | +}; | ||
| 495 | + | ||
| 496 | +/* Information about the pressure limit for a particular register class. | ||
| 497 | + This structure is used when applying a model schedule to the main | ||
| 498 | + schedule. */ | ||
| 499 | +struct model_pressure_limit { | ||
| 500 | + /* The maximum register pressure seen in the original model schedule. */ | ||
| 501 | + int orig_pressure; | ||
| 502 | + | ||
| 503 | + /* The maximum register pressure seen in the current model schedule | ||
| 504 | + (which excludes instructions that have already been scheduled). */ | ||
| 505 | + int pressure; | ||
| 506 | + | ||
| 507 | + /* The point of the current model schedule at which PRESSURE is first | ||
| 508 | + reached. It is set to -1 if the value needs to be recomputed. */ | ||
| 509 | + int point; | ||
| 510 | +}; | ||
| 511 | + | ||
| 512 | +/* Describes a particular way of measuring register pressure. */ | ||
| 513 | +struct model_pressure_group { | ||
| 514 | + /* Index CCI describes the maximum pressure on ira_reg_class_cover[CCI]. */ | ||
| 515 | + struct model_pressure_limit limits[N_REG_CLASSES]; | ||
| 516 | + | ||
| 517 | + /* Index (POINT * ira_num_pressure_classes + CCI) describes the pressure | ||
| 518 | + on register class ira_reg_class_cover[CCI] at point POINT of the | ||
| 519 | + current model schedule. A POINT of model_num_insns describes the | ||
| 520 | + pressure at the end of the schedule. */ | ||
| 521 | + struct model_pressure_data *model; | ||
| 522 | +}; | ||
| 523 | + | ||
| 524 | +/* Index POINT gives the instruction at point POINT of the model schedule. | ||
| 525 | + This array doesn't change during main scheduling. */ | ||
| 526 | +static VEC (rtx, heap) *model_schedule; | ||
| 527 | + | ||
| 528 | +/* The list of instructions in the model worklist, sorted in order of | ||
| 529 | + decreasing priority. */ | ||
| 530 | +static struct model_insn_info *model_worklist; | ||
| 531 | + | ||
| 532 | +/* Index I describes the instruction with INSN_LUID I. */ | ||
| 533 | +static struct model_insn_info *model_insns; | ||
| 534 | + | ||
| 535 | +/* The number of instructions in the model schedule. */ | ||
| 536 | +static int model_num_insns; | ||
| 537 | + | ||
| 538 | +/* The index of the first instruction in model_schedule that hasn't yet been | ||
| 539 | + added to the main schedule, or model_num_insns if all of them have. */ | ||
| 540 | +static int model_curr_point; | ||
| 541 | + | ||
| 542 | +/* Describes the pressure before each instruction in the model schedule. */ | ||
| 543 | +static struct model_pressure_group model_before_pressure; | ||
| 544 | + | ||
| 545 | +/* The first unused model_priority value (as used in model_insn_info). */ | ||
| 546 | +static unsigned int model_next_priority; | ||
| 547 | + | ||
| 548 | + | ||
| 549 | +/* The model_pressure_data for ira_reg_class_cover[CCI] in GROUP | ||
| 550 | + at point POINT of the model schedule. */ | ||
| 551 | +#define MODEL_PRESSURE_DATA(GROUP, POINT, CCI) \ | ||
| 552 | + (&(GROUP)->model[(POINT) * ira_reg_class_cover_size + (CCI)]) | ||
| 553 | + | ||
| 554 | +/* The maximum pressure on ira_reg_class_cover[CCI] in GROUP at or | ||
| 555 | + after point POINT of the model schedule. */ | ||
| 556 | +#define MODEL_MAX_PRESSURE(GROUP, POINT, CCI) \ | ||
| 557 | + (MODEL_PRESSURE_DATA (GROUP, POINT, CCI)->max_pressure) | ||
| 558 | + | ||
| 559 | +/* The pressure on ira_reg_class_cover[CCI] in GROUP at point POINT | ||
| 560 | + of the model schedule. */ | ||
| 561 | +#define MODEL_REF_PRESSURE(GROUP, POINT, CCI) \ | ||
| 562 | + (MODEL_PRESSURE_DATA (GROUP, POINT, CCI)->ref_pressure) | ||
| 563 | + | ||
| 564 | +/* Information about INSN that is used when creating the model schedule. */ | ||
| 565 | +#define MODEL_INSN_INFO(INSN) \ | ||
| 566 | + (&model_insns[INSN_LUID (INSN)]) | ||
| 567 | + | ||
| 568 | +/* The instruction at point POINT of the model schedule. */ | ||
| 569 | +#define MODEL_INSN(POINT) \ | ||
| 570 | + (VEC_index (rtx, model_schedule, POINT)) | ||
| 571 | + | ||
| 572 | + | ||
| 573 | +/* Return INSN's index in the model schedule, or model_num_insns if it | ||
| 574 | + doesn't belong to that schedule. */ | ||
| 575 | + | ||
| 576 | +static int | ||
| 577 | +model_index (rtx insn) | ||
| 578 | +{ | ||
| 579 | + if (INSN_MODEL_INDEX (insn) == 0) | ||
| 580 | + return model_num_insns; | ||
| 581 | + return INSN_MODEL_INDEX (insn) - 1; | ||
| 582 | +} | ||
| 583 | + | ||
| 584 | +/* Make sure that GROUP->limits is up-to-date for the current point | ||
| 585 | + of the model schedule. */ | ||
| 586 | + | ||
| 587 | +static void | ||
| 588 | +model_update_limit_points_in_group (struct model_pressure_group *group) | ||
| 589 | +{ | ||
| 590 | + int cci, max_pressure, point; | ||
| 591 | + | ||
| 592 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 593 | + { | ||
| 594 | + /* We may have passed the final point at which the pressure in | ||
| 595 | + group->limits[cci].pressure was reached. Update the limit if so. */ | ||
| 596 | + max_pressure = MODEL_MAX_PRESSURE (group, model_curr_point, cci); | ||
| 597 | + group->limits[cci].pressure = max_pressure; | ||
| 598 | + | ||
| 599 | + /* Find the point at which MAX_PRESSURE is first reached. We need | ||
| 600 | + to search in three cases: | ||
| 601 | + | ||
| 602 | + - We've already moved past the previous pressure point. | ||
| 603 | + In this case we search forward from model_curr_point. | ||
| 604 | + | ||
| 605 | + - We scheduled the previous point of maximum pressure ahead of | ||
| 606 | + its position in the model schedule, but doing so didn't bring | ||
| 607 | + the pressure point earlier. In this case we search forward | ||
| 608 | + from that previous pressure point. | ||
| 609 | + | ||
| 610 | + - Scheduling an instruction early caused the maximum pressure | ||
| 611 | + to decrease. In this case we will have set the pressure | ||
| 612 | + point to -1, and we search forward from model_curr_point. */ | ||
| 613 | + point = MAX (group->limits[cci].point, model_curr_point); | ||
| 614 | + while (point < model_num_insns | ||
| 615 | + && MODEL_REF_PRESSURE (group, point, cci) < max_pressure) | ||
| 616 | + point++; | ||
| 617 | + group->limits[cci].point = point; | ||
| 618 | + | ||
| 619 | + gcc_assert (MODEL_REF_PRESSURE (group, point, cci) == max_pressure); | ||
| 620 | + gcc_assert (MODEL_MAX_PRESSURE (group, point, cci) == max_pressure); | ||
| 621 | + } | ||
| 622 | +} | ||
| 623 | + | ||
| 624 | +/* Make sure that all register-pressure limits are up-to-date for the | ||
| 625 | + current position in the model schedule. */ | ||
| 626 | + | ||
| 627 | +static void | ||
| 628 | +model_update_limit_points (void) | ||
| 629 | +{ | ||
| 630 | + model_update_limit_points_in_group (&model_before_pressure); | ||
| 631 | +} | ||
| 632 | + | ||
| 633 | +/* Return the model_index of the last unscheduled use in chain USE | ||
| 634 | + outside of USE's instruction. Return -1 if there are no other uses, | ||
| 635 | + or model_num_insns if the register is live at the end of the block. */ | ||
| 636 | + | ||
| 637 | +static int | ||
| 638 | +model_last_use_except (struct reg_use_data *use) | ||
| 639 | +{ | ||
| 640 | + struct reg_use_data *next; | ||
| 641 | + int last, index; | ||
| 642 | + | ||
| 643 | + last = -1; | ||
| 644 | + for (next = use->next_regno_use; next != use; next = next->next_regno_use) | ||
| 645 | + if (NONDEBUG_INSN_P (next->insn) | ||
| 646 | + && QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED) | ||
| 647 | + { | ||
| 648 | + index = model_index (next->insn); | ||
| 649 | + if (index == model_num_insns) | ||
| 650 | + return model_num_insns; | ||
| 651 | + if (last < index) | ||
| 652 | + last = index; | ||
| 653 | + } | ||
| 654 | + return last; | ||
| 655 | +} | ||
| 656 | + | ||
| 657 | +/* An instruction with model_index POINT has just been scheduled, and it | ||
| 658 | + adds DELTA to the pressure on ira_reg_class_cover[CCI] after POINT - 1. | ||
| 659 | + Update MODEL_REF_PRESSURE (GROUP, POINT, CCI) and | ||
| 660 | + MODEL_MAX_PRESSURE (GROUP, POINT, CCI) accordingly. */ | ||
| 661 | + | ||
| 662 | +static void | ||
| 663 | +model_start_update_pressure (struct model_pressure_group *group, | ||
| 664 | + int point, int cci, int delta) | ||
| 665 | +{ | ||
| 666 | + int next_max_pressure; | ||
| 667 | + | ||
| 668 | + if (point == model_num_insns) | ||
| 669 | + { | ||
| 670 | + /* The instruction wasn't part of the model schedule; it was moved | ||
| 671 | + from a different block. Update the pressure for the end of | ||
| 672 | + the model schedule. */ | ||
| 673 | + MODEL_REF_PRESSURE (group, point, cci) += delta; | ||
| 674 | + MODEL_MAX_PRESSURE (group, point, cci) += delta; | ||
| 675 | + } | ||
| 676 | + else | ||
| 677 | + { | ||
| 678 | + /* Record that this instruction has been scheduled. Nothing now | ||
| 679 | + changes between POINT and POINT + 1, so get the maximum pressure | ||
| 680 | + from the latter. If the maximum pressure decreases, the new | ||
| 681 | + pressure point may be before POINT. */ | ||
| 682 | + MODEL_REF_PRESSURE (group, point, cci) = -1; | ||
| 683 | + next_max_pressure = MODEL_MAX_PRESSURE (group, point + 1, cci); | ||
| 684 | + if (MODEL_MAX_PRESSURE (group, point, cci) > next_max_pressure) | ||
| 685 | + { | ||
| 686 | + MODEL_MAX_PRESSURE (group, point, cci) = next_max_pressure; | ||
| 687 | + if (group->limits[cci].point == point) | ||
| 688 | + group->limits[cci].point = -1; | ||
| 689 | + } | ||
| 690 | + } | ||
| 691 | +} | ||
| 692 | + | ||
| 693 | +/* Record that scheduling a later instruction has changed the pressure | ||
| 694 | + at point POINT of the model schedule by DELTA (which might be 0). | ||
| 695 | + Update GROUP accordingly. Return nonzero if these changes might | ||
| 696 | + trigger changes to previous points as well. */ | ||
| 697 | + | ||
| 698 | +static int | ||
| 699 | +model_update_pressure (struct model_pressure_group *group, | ||
| 700 | + int point, int cci, int delta) | ||
| 701 | +{ | ||
| 702 | + int ref_pressure, max_pressure, next_max_pressure; | ||
| 703 | + | ||
| 704 | + /* If POINT hasn't yet been scheduled, update its pressure. */ | ||
| 705 | + ref_pressure = MODEL_REF_PRESSURE (group, point, cci); | ||
| 706 | + if (ref_pressure >= 0 && delta != 0) | ||
| 707 | + { | ||
| 708 | + ref_pressure += delta; | ||
| 709 | + MODEL_REF_PRESSURE (group, point, cci) = ref_pressure; | ||
| 710 | + | ||
| 711 | + /* Check whether the maximum pressure in the overall schedule | ||
| 712 | + has increased. (This means that the MODEL_MAX_PRESSURE of | ||
| 713 | + every point <= POINT will need to increae too; see below.) */ | ||
| 714 | + if (group->limits[cci].pressure < ref_pressure) | ||
| 715 | + group->limits[cci].pressure = ref_pressure; | ||
| 716 | + | ||
| 717 | + /* If we are at maximum pressure, and the maximum pressure | ||
| 718 | + point was previously unknown or later than POINT, | ||
| 719 | + bring it forward. */ | ||
| 720 | + if (group->limits[cci].pressure == ref_pressure | ||
| 721 | + && !IN_RANGE (group->limits[cci].point, 0, point)) | ||
| 722 | + group->limits[cci].point = point; | ||
| 723 | + | ||
| 724 | + /* If POINT used to be the point of maximum pressure, but isn't | ||
| 725 | + any longer, we need to recalculate it using a forward walk. */ | ||
| 726 | + if (group->limits[cci].pressure > ref_pressure | ||
| 727 | + && group->limits[cci].point == point) | ||
| 728 | + group->limits[cci].point = -1; | ||
| 729 | + } | ||
| 730 | + | ||
| 731 | + /* Update the maximum pressure at POINT. Changes here might also | ||
| 732 | + affect the maximum pressure at POINT - 1. */ | ||
| 733 | + next_max_pressure = MODEL_MAX_PRESSURE (group, point + 1, cci); | ||
| 734 | + max_pressure = MAX (ref_pressure, next_max_pressure); | ||
| 735 | + if (MODEL_MAX_PRESSURE (group, point, cci) != max_pressure) | ||
| 736 | + { | ||
| 737 | + MODEL_MAX_PRESSURE (group, point, cci) = max_pressure; | ||
| 738 | + return 1; | ||
| 739 | + } | ||
| 740 | + return 0; | ||
| 741 | +} | ||
| 742 | + | ||
| 743 | +/* INSN has just been scheduled. Update the model schedule accordingly. */ | ||
| 744 | + | ||
| 745 | +static void | ||
| 746 | +model_recompute (rtx insn) | ||
| 747 | +{ | ||
| 748 | + struct { | ||
| 749 | + int last_use; | ||
| 750 | + int regno; | ||
| 751 | + } uses[FIRST_PSEUDO_REGISTER + MAX_RECOG_OPERANDS]; | ||
| 752 | + struct reg_use_data *use; | ||
| 753 | + struct reg_pressure_data *reg_pressure; | ||
| 754 | + int delta[N_REG_CLASSES]; | ||
| 755 | + int cci, point, mix, new_last, cl, ref_pressure, queue; | ||
| 756 | + unsigned int i, num_uses, num_pending_births; | ||
| 757 | + bool print_p; | ||
| 758 | + | ||
| 759 | + /* The destinations of INSN were previously live from POINT onwards, but are | ||
| 760 | + now live from model_curr_point onwards. Set up DELTA accordingly. */ | ||
| 761 | + point = model_index (insn); | ||
| 762 | + reg_pressure = INSN_REG_PRESSURE (insn); | ||
| 763 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 764 | + { | ||
| 765 | + cl = ira_reg_class_cover[cci]; | ||
| 766 | + delta[cl] = reg_pressure[cci].set_increase; | ||
| 767 | + } | ||
| 768 | + | ||
| 769 | + /* Record which registers previously died at POINT, but which now die | ||
| 770 | + before POINT. Adjust DELTA so that it represents the effect of | ||
| 771 | + this change after POINT - 1. Set NUM_PENDING_BIRTHS to the number of | ||
| 772 | + registers that will be born in the range [model_curr_point, POINT). */ | ||
| 773 | + num_uses = 0; | ||
| 774 | + num_pending_births = 0; | ||
| 775 | + for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
| 776 | + { | ||
| 777 | + new_last = model_last_use_except (use); | ||
| 778 | + if (new_last < point) | ||
| 779 | + { | ||
| 780 | + gcc_assert (num_uses < ARRAY_SIZE (uses)); | ||
| 781 | + uses[num_uses].last_use = new_last; | ||
| 782 | + uses[num_uses].regno = use->regno; | ||
| 783 | + /* This register is no longer live after POINT - 1. */ | ||
| 784 | + mark_regno_birth_or_death (NULL, delta, use->regno, false); | ||
| 785 | + num_uses++; | ||
| 786 | + if (new_last >= 0) | ||
| 787 | + num_pending_births++; | ||
| 788 | + } | ||
| 789 | + } | ||
| 790 | + | ||
| 791 | + /* Update the MODEL_REF_PRESSURE and MODEL_MAX_PRESSURE for POINT. | ||
| 792 | + Also set each group pressure limit for POINT. */ | ||
| 793 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 794 | + { | ||
| 795 | + cl = ira_reg_class_cover[cci]; | ||
| 796 | + model_start_update_pressure (&model_before_pressure, | ||
| 797 | + point, cci, delta[cl]); | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + /* Walk the model schedule backwards, starting immediately before POINT. */ | ||
| 801 | + print_p = false; | ||
| 802 | + if (point != model_curr_point) | ||
| 803 | + do | ||
| 804 | + { | ||
| 805 | + point--; | ||
| 806 | + insn = MODEL_INSN (point); | ||
| 807 | + queue = QUEUE_INDEX (insn); | ||
| 808 | + | ||
| 809 | + if (queue != QUEUE_SCHEDULED) | ||
| 810 | + { | ||
| 811 | + /* DELTA describes the effect of the move on the register pressure | ||
| 812 | + after POINT. Make it describe the effect on the pressure | ||
| 813 | + before POINT. */ | ||
| 814 | + i = 0; | ||
| 815 | + while (i < num_uses) | ||
| 816 | + { | ||
| 817 | + if (uses[i].last_use == point) | ||
| 818 | + { | ||
| 819 | + /* This register is now live again. */ | ||
| 820 | + mark_regno_birth_or_death (NULL, delta, | ||
| 821 | + uses[i].regno, true); | ||
| 822 | + | ||
| 823 | + /* Remove this use from the array. */ | ||
| 824 | + uses[i] = uses[num_uses - 1]; | ||
| 825 | + num_uses--; | ||
| 826 | + num_pending_births--; | ||
| 827 | + } | ||
| 828 | + else | ||
| 829 | + i++; | ||
| 830 | + } | ||
| 831 | + | ||
| 832 | + if (sched_verbose >= 5) | ||
| 833 | + { | ||
| 834 | + char buf[2048]; | ||
| 835 | + | ||
| 836 | + if (!print_p) | ||
| 837 | + { | ||
| 838 | + fprintf (sched_dump, MODEL_BAR); | ||
| 839 | + fprintf (sched_dump, ";;\t\t| New pressure for model" | ||
| 840 | + " schedule\n"); | ||
| 841 | + fprintf (sched_dump, MODEL_BAR); | ||
| 842 | + print_p = true; | ||
| 843 | + } | ||
| 844 | + | ||
| 845 | + print_pattern (buf, PATTERN (insn), 0); | ||
| 846 | + fprintf (sched_dump, ";;\t\t| %3d %4d %-30s ", | ||
| 847 | + point, INSN_UID (insn), buf); | ||
| 848 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 849 | + { | ||
| 850 | + cl = ira_reg_class_cover[cci]; | ||
| 851 | + ref_pressure = MODEL_REF_PRESSURE (&model_before_pressure, | ||
| 852 | + point, cci); | ||
| 853 | + fprintf (sched_dump, " %s:[%d->%d]", | ||
| 854 | + reg_class_names[ira_reg_class_cover[cci]], | ||
| 855 | + ref_pressure, ref_pressure + delta[cl]); | ||
| 856 | + } | ||
| 857 | + fprintf (sched_dump, "\n"); | ||
| 858 | + } | ||
| 859 | + } | ||
| 860 | + | ||
| 861 | + /* Adjust the pressure at POINT. Set MIX to nonzero if POINT - 1 | ||
| 862 | + might have changed as well. */ | ||
| 863 | + mix = num_pending_births; | ||
| 864 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 865 | + { | ||
| 866 | + cl = ira_reg_class_cover[cci]; | ||
| 867 | + mix |= delta[cl]; | ||
| 868 | + mix |= model_update_pressure (&model_before_pressure, | ||
| 869 | + point, cci, delta[cl]); | ||
| 870 | + } | ||
| 871 | + } | ||
| 872 | + while (mix && point > model_curr_point); | ||
| 873 | + | ||
| 874 | + if (print_p) | ||
| 875 | + fprintf (sched_dump, MODEL_BAR); | ||
| 876 | +} | ||
| 877 | + | ||
| 878 | +/* model_spill_cost (CL, P, P') returns the cost of increasing the | ||
| 879 | + pressure on CL from P to P'. We use this to calculate a "base ECC", | ||
| 880 | + baseECC (CL, X), for each cover class CL and each instruction X. | ||
| 881 | + Supposing X changes the pressure on CL from P to P', and that the | ||
| 882 | + maximum pressure on CL in the current model schedule is MP', then: | ||
| 883 | + | ||
| 884 | + * if X occurs before or at the next point of maximum pressure in | ||
| 885 | + the model schedule and P' > MP', then: | ||
| 886 | + | ||
| 887 | + baseECC (CL, X) = model_spill_cost (CL, MP, P') | ||
| 888 | + | ||
| 889 | + The idea is that the pressure after scheduling a fixed set of | ||
| 890 | + instructions -- in this case, the set up to and including the | ||
| 891 | + next maximum pressure point -- is going to be the same regardless | ||
| 892 | + of the order; we simply want to keep the intermediate pressure | ||
| 893 | + under control. Thus X has a cost of zero unless scheduling it | ||
| 894 | + now would exceed MP'. | ||
| 895 | + | ||
| 896 | + If all increases in the set are by the same amount, no zero-cost | ||
| 897 | + instruction will ever cause the pressure to exceed MP'. However, | ||
| 898 | + if X is instead moved past an instruction X' with pressure in the | ||
| 899 | + range (MP' - (P' - P), MP'), the pressure at X' will increase | ||
| 900 | + beyond MP'. Since baseECC is very much a heuristic anyway, | ||
| 901 | + it doesn't seem worth the overhead of tracking cases like these. | ||
| 902 | + | ||
| 903 | + The cost of exceeding MP' is always based on the original maximum | ||
| 904 | + pressure MP. This is so that going 2 registers over the original | ||
| 905 | + limit has the same cost regardless of whether it comes from two | ||
| 906 | + separate +1 deltas or from a single +2 delta. | ||
| 907 | + | ||
| 908 | + * if X occurs after the next point of maximum pressure in the model | ||
| 909 | + schedule and P' > P, then: | ||
| 910 | + | ||
| 911 | + baseECC (CL, X) = model_spill_cost (CL, MP, MP' + (P' - P)) | ||
| 912 | + | ||
| 913 | + That is, if we move X forward across a point of maximum pressure, | ||
| 914 | + and if X increases the pressure by P' - P, then we conservatively | ||
| 915 | + assume that scheduling X next would increase the maximum pressure | ||
| 916 | + by P' - P. Again, the cost of doing this is based on the original | ||
| 917 | + maximum pressure MP, for the same reason as above. | ||
| 918 | + | ||
| 919 | + * if P' < P, P > MP, and X occurs at or after the next point of | ||
| 920 | + maximum pressure, then: | ||
| 921 | + | ||
| 922 | + baseECC (CL, X) = -model_spill_cost (CL, MAX (MP, P'), P) | ||
| 923 | + | ||
| 924 | + That is, if we have already exceeded the original maximum pressure MP, | ||
| 925 | + and if X might reduce the maximum pressure again -- or at least push | ||
| 926 | + it further back, and thus allow more scheduling freedom -- it is given | ||
| 927 | + a negative cost to reflect the improvement. | ||
| 928 | + | ||
| 929 | + * otherwise, | ||
| 930 | + | ||
| 931 | + baseECC (CL, X) = 0 | ||
| 932 | + | ||
| 933 | + In this case, X is not expected to affect the maximum pressure MP', | ||
| 934 | + so it has zero cost. | ||
| 935 | + | ||
| 936 | + We then create a combined value baseECC (X) that is the sum of | ||
| 937 | + baseECC (CL, X) for each cover class CL. | ||
| 938 | + | ||
| 939 | + baseECC (X) could itself be used as the ECC value described above. | ||
| 940 | + However, this is often too conservative, in the sense that it | ||
| 941 | + tends to make high-priority instructions that increase pressure | ||
| 942 | + wait too long in cases where introducing a spill would be better. | ||
| 943 | + For this reason the final ECC is a priority-adjusted form of | ||
| 944 | + baseECC (X). Specifically, we calculate: | ||
| 945 | + | ||
| 946 | + P (X) = INSN_PRIORITY (X) - insn_delay (X) - baseECC (X) | ||
| 947 | + baseP = MAX { P (X) | baseECC (X) <= 0 } | ||
| 948 | + | ||
| 949 | + Then: | ||
| 950 | + | ||
| 951 | + ECC (X) = MAX (MIN (baseP - P (X), baseECC (X)), 0) | ||
| 952 | + | ||
| 953 | + Thus an instruction's effect on pressure is ignored if it has a high | ||
| 954 | + enough priority relative to the ones that don't increase pressure. | ||
| 955 | + Negative values of baseECC (X) do not increase the priority of X | ||
| 956 | + itself, but they do make it harder for other instructions to | ||
| 957 | + increase the pressure further. | ||
| 958 | + | ||
| 959 | + This pressure cost is deliberately timid. The intention has been | ||
| 960 | + to choose a heuristic that rarely interferes with the normal list | ||
| 961 | + scheduler in cases where that scheduler would produce good code. | ||
| 962 | + We simply want to curb some of its worst excesses. */ | ||
| 963 | + | ||
| 964 | +/* Return the cost of increasing the pressure in class CL from FROM to TO. | ||
| 965 | + | ||
| 966 | + Here we use the very simplistic cost model that every register above | ||
| 967 | + ira_available_class_regs[CL] has a spill cost of 1. We could use other | ||
| 968 | + measures instead, such as one based on MEMORY_MOVE_COST. However: | ||
| 969 | + | ||
| 970 | + (1) In order for an instruction to be scheduled, the higher cost | ||
| 971 | + would need to be justified in a single saving of that many stalls. | ||
| 972 | + This is overly pessimistic, because the benefit of spilling is | ||
| 973 | + often to avoid a sequence of several short stalls rather than | ||
| 974 | + a single long one. | ||
| 975 | + | ||
| 976 | + (2) The cost is still arbitrary. Because we are not allocating | ||
| 977 | + registers during scheduling, we have no way of knowing for | ||
| 978 | + sure how many memory accesses will be required by each spill, | ||
| 979 | + where the spills will be placed within the block, or even | ||
| 980 | + which block(s) will contain the spills. | ||
| 981 | + | ||
| 982 | + So a higher cost than 1 is often too conservative in practice, | ||
| 983 | + forcing blocks to contain unnecessary stalls instead of spill code. | ||
| 984 | + The simple cost below seems to be the best compromise. It reduces | ||
| 985 | + the interference with the normal list scheduler, which helps make | ||
| 986 | + it more suitable for a default-on option. */ | ||
| 987 | + | ||
| 988 | +static int | ||
| 989 | +model_spill_cost (int cl, int from, int to) | ||
| 990 | +{ | ||
| 991 | + from = MAX (from, ira_available_class_regs[cl]); | ||
| 992 | + return MAX (to, from) - from; | ||
| 993 | +} | ||
| 994 | + | ||
| 995 | +/* Return baseECC (ira_reg_class_cover[CCI], POINT), given that | ||
| 996 | + P = curr_reg_pressure[ira_reg_class_cover[CCI]] and that | ||
| 997 | + P' = P + DELTA. */ | ||
| 998 | + | ||
| 999 | +static int | ||
| 1000 | +model_excess_group_cost (struct model_pressure_group *group, | ||
| 1001 | + int point, int cci, int delta) | ||
| 1002 | +{ | ||
| 1003 | + int pressure, cl; | ||
| 1004 | + | ||
| 1005 | + cl = ira_reg_class_cover[cci]; | ||
| 1006 | + if (delta < 0 && point >= group->limits[cci].point) | ||
| 1007 | + { | ||
| 1008 | + pressure = MAX (group->limits[cci].orig_pressure, | ||
| 1009 | + curr_reg_pressure[cl] + delta); | ||
| 1010 | + return -model_spill_cost (cl, pressure, curr_reg_pressure[cl]); | ||
| 1011 | + } | ||
| 1012 | + | ||
| 1013 | + if (delta > 0) | ||
| 1014 | + { | ||
| 1015 | + if (point > group->limits[cci].point) | ||
| 1016 | + pressure = group->limits[cci].pressure + delta; | ||
| 1017 | + else | ||
| 1018 | + pressure = curr_reg_pressure[cl] + delta; | ||
| 1019 | + | ||
| 1020 | + if (pressure > group->limits[cci].pressure) | ||
| 1021 | + return model_spill_cost (cl, group->limits[cci].orig_pressure, | ||
| 1022 | + pressure); | ||
| 1023 | + } | ||
| 1024 | + | ||
| 1025 | + return 0; | ||
| 1026 | +} | ||
| 1027 | + | ||
| 1028 | +/* Return baseECC (MODEL_INSN (INSN)). Dump the costs to sched_dump | ||
| 1029 | + if PRINT_P. */ | ||
| 1030 | + | ||
| 1031 | +static int | ||
| 1032 | +model_excess_cost (rtx insn, bool print_p) | ||
| 1033 | +{ | ||
| 1034 | + int point, cci, cl, cost, this_cost, delta; | ||
| 1035 | + struct reg_pressure_data *insn_reg_pressure; | ||
| 1036 | + int insn_death[N_REG_CLASSES]; | ||
| 1037 | + | ||
| 1038 | + calculate_reg_deaths (insn, insn_death); | ||
| 1039 | + point = model_index (insn); | ||
| 1040 | + insn_reg_pressure = INSN_REG_PRESSURE (insn); | ||
| 1041 | + cost = 0; | ||
| 1042 | + | ||
| 1043 | + if (print_p) | ||
| 1044 | + fprintf (sched_dump, ";;\t\t| %3d %4d | %4d %+3d |", point, | ||
| 1045 | + INSN_UID (insn), INSN_PRIORITY (insn), insn_delay (insn)); | ||
| 1046 | + | ||
| 1047 | + /* Sum up the individual costs for each register class. */ | ||
| 1048 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1049 | + { | ||
| 1050 | + cl = ira_reg_class_cover[cci]; | ||
| 1051 | + delta = insn_reg_pressure[cci].set_increase - insn_death[cl]; | ||
| 1052 | + this_cost = model_excess_group_cost (&model_before_pressure, | ||
| 1053 | + point, cci, delta); | ||
| 1054 | + cost += this_cost; | ||
| 1055 | + if (print_p) | ||
| 1056 | + fprintf (sched_dump, " %s:[%d base cost %d]", | ||
| 1057 | + reg_class_names[cl], delta, this_cost); | ||
| 1058 | + } | ||
| 1059 | + | ||
| 1060 | + if (print_p) | ||
| 1061 | + fprintf (sched_dump, "\n"); | ||
| 1062 | + | ||
| 1063 | + return cost; | ||
| 1064 | +} | ||
| 1065 | + | ||
| 1066 | +/* Dump the next points of maximum pressure for GROUP. */ | ||
| 1067 | + | ||
| 1068 | +static void | ||
| 1069 | +model_dump_pressure_points (struct model_pressure_group *group) | ||
| 1070 | +{ | ||
| 1071 | + int cci, cl; | ||
| 1072 | + | ||
| 1073 | + fprintf (sched_dump, ";;\t\t| pressure points"); | ||
| 1074 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1075 | + { | ||
| 1076 | + cl = ira_reg_class_cover[cci]; | ||
| 1077 | + fprintf (sched_dump, " %s:[%d->%d at ", reg_class_names[cl], | ||
| 1078 | + curr_reg_pressure[cl], group->limits[cci].pressure); | ||
| 1079 | + if (group->limits[cci].point < model_num_insns) | ||
| 1080 | + fprintf (sched_dump, "%d:%d]", group->limits[cci].point, | ||
| 1081 | + INSN_UID (MODEL_INSN (group->limits[cci].point))); | ||
| 1082 | + else | ||
| 1083 | + fprintf (sched_dump, "end]"); | ||
| 1084 | + } | ||
| 1085 | + fprintf (sched_dump, "\n"); | ||
| 1086 | +} | ||
| 1087 | + | ||
| 1088 | +/* Set INSN_REG_PRESSURE_EXCESS_COST_CHANGE for INSNS[0...COUNT-1]. */ | ||
| 1089 | + | ||
| 1090 | +static void | ||
| 1091 | +model_set_excess_costs (rtx *insns, int count) | ||
| 1092 | +{ | ||
| 1093 | + int i, cost, priority_base, priority; | ||
| 1094 | + bool print_p; | ||
| 1095 | + | ||
| 1096 | + /* Record the baseECC value for each instruction in the model schedule, | ||
| 1097 | + except that negative costs are converted to zero ones now rather thatn | ||
| 1098 | + later. Do not assign a cost to debug instructions, since they must | ||
| 1099 | + not change code-generation decisions. Experiments suggest we also | ||
| 1100 | + get better results by not assigning a cost to instructions from | ||
| 1101 | + a different block. | ||
| 1102 | + | ||
| 1103 | + Set PRIORITY_BASE to baseP in the block comment above. This is the | ||
| 1104 | + maximum priority of the "cheap" instructions, which should always | ||
| 1105 | + include the next model instruction. */ | ||
| 1106 | + priority_base = 0; | ||
| 1107 | + print_p = false; | ||
| 1108 | + for (i = 0; i < count; i++) | ||
| 1109 | + if (INSN_MODEL_INDEX (insns[i])) | ||
| 1110 | + { | ||
| 1111 | + if (sched_verbose >= 6 && !print_p) | ||
| 1112 | + { | ||
| 1113 | + fprintf (sched_dump, MODEL_BAR); | ||
| 1114 | + fprintf (sched_dump, ";;\t\t| Pressure costs for ready queue\n"); | ||
| 1115 | + model_dump_pressure_points (&model_before_pressure); | ||
| 1116 | + fprintf (sched_dump, MODEL_BAR); | ||
| 1117 | + print_p = true; | ||
| 1118 | + } | ||
| 1119 | + cost = model_excess_cost (insns[i], print_p); | ||
| 1120 | + if (cost <= 0) | ||
| 1121 | + { | ||
| 1122 | + priority = INSN_PRIORITY (insns[i]) - insn_delay (insns[i]) - cost; | ||
| 1123 | + priority_base = MAX (priority_base, priority); | ||
| 1124 | + cost = 0; | ||
| 1125 | + } | ||
| 1126 | + INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]) = cost; | ||
| 1127 | + } | ||
| 1128 | + if (print_p) | ||
| 1129 | + fprintf (sched_dump, MODEL_BAR); | ||
| 1130 | + | ||
| 1131 | + /* Use MAX (baseECC, 0) and baseP to calculcate ECC for each | ||
| 1132 | + instruction. */ | ||
| 1133 | + for (i = 0; i < count; i++) | ||
| 1134 | + { | ||
| 1135 | + cost = INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]); | ||
| 1136 | + priority = INSN_PRIORITY (insns[i]) - insn_delay (insns[i]); | ||
| 1137 | + if (cost > 0 && priority > priority_base) | ||
| 1138 | + { | ||
| 1139 | + cost += priority_base - priority; | ||
| 1140 | + INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]) = MAX (cost, 0); | ||
| 1141 | + } | ||
| 1142 | + } | ||
| 1143 | +} | ||
| 1144 | + | ||
| 1145 | /* Returns a positive value if x is preferred; returns a negative value if | ||
| 1146 | y is preferred. Should never return 0, since that will make the sort | ||
| 1147 | unstable. */ | ||
| 1148 | @@ -1170,23 +1948,20 @@ | ||
| 1149 | /* Make sure that priority of TMP and TMP2 are initialized. */ | ||
| 1150 | gcc_assert (INSN_PRIORITY_KNOWN (tmp) && INSN_PRIORITY_KNOWN (tmp2)); | ||
| 1151 | |||
| 1152 | - if (sched_pressure_p) | ||
| 1153 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 1154 | { | ||
| 1155 | int diff; | ||
| 1156 | |||
| 1157 | /* Prefer insn whose scheduling results in the smallest register | ||
| 1158 | pressure excess. */ | ||
| 1159 | if ((diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp) | ||
| 1160 | - + (INSN_TICK (tmp) > clock_var | ||
| 1161 | - ? INSN_TICK (tmp) - clock_var : 0) | ||
| 1162 | + + insn_delay (tmp) | ||
| 1163 | - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2) | ||
| 1164 | - - (INSN_TICK (tmp2) > clock_var | ||
| 1165 | - ? INSN_TICK (tmp2) - clock_var : 0))) != 0) | ||
| 1166 | + - insn_delay (tmp2)))) | ||
| 1167 | return diff; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | - | ||
| 1171 | - if (sched_pressure_p | ||
| 1172 | + if (sched_pressure != SCHED_PRESSURE_NONE | ||
| 1173 | && (INSN_TICK (tmp2) > clock_var || INSN_TICK (tmp) > clock_var)) | ||
| 1174 | { | ||
| 1175 | if (INSN_TICK (tmp) <= clock_var) | ||
| 1176 | @@ -1277,11 +2052,22 @@ | ||
| 1177 | return val; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | + /* Prefer instructions that occur earlier in the model schedule. */ | ||
| 1181 | + if (sched_pressure == SCHED_PRESSURE_MODEL) | ||
| 1182 | + { | ||
| 1183 | + int diff; | ||
| 1184 | + | ||
| 1185 | + diff = model_index (tmp) - model_index (tmp2); | ||
| 1186 | + if (diff != 0) | ||
| 1187 | + return diff; | ||
| 1188 | + } | ||
| 1189 | + | ||
| 1190 | /* Prefer the insn which has more later insns that depend on it. | ||
| 1191 | This gives the scheduler more freedom when scheduling later | ||
| 1192 | instructions at the expense of added register pressure. */ | ||
| 1193 | |||
| 1194 | - val = (dep_list_size (tmp2) - dep_list_size (tmp)); | ||
| 1195 | + val = (dep_list_size (tmp2, SD_LIST_FORW) | ||
| 1196 | + - dep_list_size (tmp, SD_LIST_FORW)); | ||
| 1197 | |||
| 1198 | if (flag_sched_dep_count_heuristic && val != 0) | ||
| 1199 | return val; | ||
| 1200 | @@ -1480,12 +2266,15 @@ | ||
| 1201 | int i; | ||
| 1202 | rtx *first = ready_lastpos (ready); | ||
| 1203 | |||
| 1204 | - if (sched_pressure_p) | ||
| 1205 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
| 1206 | { | ||
| 1207 | for (i = 0; i < ready->n_ready; i++) | ||
| 1208 | if (!DEBUG_INSN_P (first[i])) | ||
| 1209 | setup_insn_reg_pressure_info (first[i]); | ||
| 1210 | } | ||
| 1211 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
| 1212 | + && model_curr_point < model_num_insns) | ||
| 1213 | + model_set_excess_costs (first, ready->n_ready); | ||
| 1214 | SCHED_SORT (first, ready->n_ready); | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | @@ -1551,10 +2340,12 @@ | ||
| 1218 | gcc_checking_assert (!DEBUG_INSN_P (insn)); | ||
| 1219 | |||
| 1220 | for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
| 1221 | - if (dying_use_p (use) && bitmap_bit_p (curr_reg_live, use->regno)) | ||
| 1222 | - mark_regno_birth_or_death (use->regno, false); | ||
| 1223 | + if (dying_use_p (use)) | ||
| 1224 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, | ||
| 1225 | + use->regno, false); | ||
| 1226 | for (set = INSN_REG_SET_LIST (insn); set != NULL; set = set->next_insn_set) | ||
| 1227 | - mark_regno_birth_or_death (set->regno, true); | ||
| 1228 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, | ||
| 1229 | + set->regno, true); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | /* Set up or update (if UPDATE_P) max register pressure (see its | ||
| 1233 | @@ -1626,11 +2417,618 @@ | ||
| 1234 | void | ||
| 1235 | sched_setup_bb_reg_pressure_info (basic_block bb, rtx after) | ||
| 1236 | { | ||
| 1237 | - gcc_assert (sched_pressure_p); | ||
| 1238 | + gcc_assert (sched_pressure == SCHED_PRESSURE_WEIGHTED); | ||
| 1239 | initiate_bb_reg_pressure_info (bb); | ||
| 1240 | setup_insn_max_reg_pressure (after, false); | ||
| 1241 | } | ||
| 1242 | - | ||
| 1243 | + | ||
| 1244 | +/* Return (in order): | ||
| 1245 | + | ||
| 1246 | + - positive if INSN adversely affects the pressure on one | ||
| 1247 | + register class | ||
| 1248 | + | ||
| 1249 | + - negative if INSN reduces the pressure on one register class | ||
| 1250 | + | ||
| 1251 | + - 0 if INSN doesn't affect the pressure on any register class. */ | ||
| 1252 | + | ||
| 1253 | +static int | ||
| 1254 | +model_classify_pressure (struct model_insn_info *insn) | ||
| 1255 | +{ | ||
| 1256 | + struct reg_pressure_data *reg_pressure; | ||
| 1257 | + int death[N_REG_CLASSES]; | ||
| 1258 | + int cci, cl, sum; | ||
| 1259 | + | ||
| 1260 | + calculate_reg_deaths (insn->insn, death); | ||
| 1261 | + reg_pressure = INSN_REG_PRESSURE (insn->insn); | ||
| 1262 | + sum = 0; | ||
| 1263 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1264 | + { | ||
| 1265 | + cl = ira_reg_class_cover[cci]; | ||
| 1266 | + if (death[cl] < reg_pressure[cci].set_increase) | ||
| 1267 | + return 1; | ||
| 1268 | + sum += reg_pressure[cci].set_increase - death[cl]; | ||
| 1269 | + } | ||
| 1270 | + return sum; | ||
| 1271 | +} | ||
| 1272 | + | ||
| 1273 | +/* Return true if INSN1 should come before INSN2 in the model schedule. */ | ||
| 1274 | + | ||
| 1275 | +static int | ||
| 1276 | +model_order_p (struct model_insn_info *insn1, struct model_insn_info *insn2) | ||
| 1277 | +{ | ||
| 1278 | + unsigned int height1, height2; | ||
| 1279 | + unsigned int priority1, priority2; | ||
| 1280 | + | ||
| 1281 | + /* Prefer instructions with a higher model priority. */ | ||
| 1282 | + if (insn1->model_priority != insn2->model_priority) | ||
| 1283 | + return insn1->model_priority > insn2->model_priority; | ||
| 1284 | + | ||
| 1285 | + /* Combine the length of the longest path of satisfied true dependencies | ||
| 1286 | + that leads to each instruction (depth) with the length of the longest | ||
| 1287 | + path of any dependencies that leads from the instruction (alap). | ||
| 1288 | + Prefer instructions with the greatest combined length. If the combined | ||
| 1289 | + lengths are equal, prefer instructions with the greatest depth. | ||
| 1290 | + | ||
| 1291 | + The idea is that, if we have a set S of "equal" instructions that each | ||
| 1292 | + have ALAP value X, and we pick one such instruction I, any true-dependent | ||
| 1293 | + successors of I that have ALAP value X - 1 should be preferred over S. | ||
| 1294 | + This encourages the schedule to be "narrow" rather than "wide". | ||
| 1295 | + However, if I is a low-priority instruction that we decided to | ||
| 1296 | + schedule because of its model_classify_pressure, and if there | ||
| 1297 | + is a set of higher-priority instructions T, the aforementioned | ||
| 1298 | + successors of I should not have the edge over T. */ | ||
| 1299 | + height1 = insn1->depth + insn1->alap; | ||
| 1300 | + height2 = insn2->depth + insn2->alap; | ||
| 1301 | + if (height1 != height2) | ||
| 1302 | + return height1 > height2; | ||
| 1303 | + if (insn1->depth != insn2->depth) | ||
| 1304 | + return insn1->depth > insn2->depth; | ||
| 1305 | + | ||
| 1306 | + /* We have no real preference between INSN1 an INSN2 as far as attempts | ||
| 1307 | + to reduce pressure go. Prefer instructions with higher priorities. */ | ||
| 1308 | + priority1 = INSN_PRIORITY (insn1->insn); | ||
| 1309 | + priority2 = INSN_PRIORITY (insn2->insn); | ||
| 1310 | + if (priority1 != priority2) | ||
| 1311 | + return priority1 > priority2; | ||
| 1312 | + | ||
| 1313 | + /* Use the original rtl sequence as a tie-breaker. */ | ||
| 1314 | + return insn1 < insn2; | ||
| 1315 | +} | ||
| 1316 | + | ||
| 1317 | +/* Add INSN to the model worklist immediately after PREV. Add it to the | ||
| 1318 | + beginning of the list if PREV is null. */ | ||
| 1319 | + | ||
| 1320 | +static void | ||
| 1321 | +model_add_to_worklist_at (struct model_insn_info *insn, | ||
| 1322 | + struct model_insn_info *prev) | ||
| 1323 | +{ | ||
| 1324 | + gcc_assert (QUEUE_INDEX (insn->insn) == QUEUE_NOWHERE); | ||
| 1325 | + QUEUE_INDEX (insn->insn) = QUEUE_READY; | ||
| 1326 | + | ||
| 1327 | + insn->prev = prev; | ||
| 1328 | + if (prev) | ||
| 1329 | + { | ||
| 1330 | + insn->next = prev->next; | ||
| 1331 | + prev->next = insn; | ||
| 1332 | + } | ||
| 1333 | + else | ||
| 1334 | + { | ||
| 1335 | + insn->next = model_worklist; | ||
| 1336 | + model_worklist = insn; | ||
| 1337 | + } | ||
| 1338 | + if (insn->next) | ||
| 1339 | + insn->next->prev = insn; | ||
| 1340 | +} | ||
| 1341 | + | ||
| 1342 | +/* Remove INSN from the model worklist. */ | ||
| 1343 | + | ||
| 1344 | +static void | ||
| 1345 | +model_remove_from_worklist (struct model_insn_info *insn) | ||
| 1346 | +{ | ||
| 1347 | + gcc_assert (QUEUE_INDEX (insn->insn) == QUEUE_READY); | ||
| 1348 | + QUEUE_INDEX (insn->insn) = QUEUE_NOWHERE; | ||
| 1349 | + | ||
| 1350 | + if (insn->prev) | ||
| 1351 | + insn->prev->next = insn->next; | ||
| 1352 | + else | ||
| 1353 | + model_worklist = insn->next; | ||
| 1354 | + if (insn->next) | ||
| 1355 | + insn->next->prev = insn->prev; | ||
| 1356 | +} | ||
| 1357 | + | ||
| 1358 | +/* Add INSN to the model worklist. Start looking for a suitable position | ||
| 1359 | + between neighbors PREV and NEXT, testing at most MAX_SCHED_READY_INSNS | ||
| 1360 | + insns either side. A null PREV indicates the beginning of the list and | ||
| 1361 | + a null NEXT indicates the end. */ | ||
| 1362 | + | ||
| 1363 | +static void | ||
| 1364 | +model_add_to_worklist (struct model_insn_info *insn, | ||
| 1365 | + struct model_insn_info *prev, | ||
| 1366 | + struct model_insn_info *next) | ||
| 1367 | +{ | ||
| 1368 | + int count; | ||
| 1369 | + | ||
| 1370 | + count = MAX_SCHED_READY_INSNS; | ||
| 1371 | + if (count > 0 && prev && model_order_p (insn, prev)) | ||
| 1372 | + do | ||
| 1373 | + { | ||
| 1374 | + count--; | ||
| 1375 | + prev = prev->prev; | ||
| 1376 | + } | ||
| 1377 | + while (count > 0 && prev && model_order_p (insn, prev)); | ||
| 1378 | + else | ||
| 1379 | + while (count > 0 && next && model_order_p (next, insn)) | ||
| 1380 | + { | ||
| 1381 | + count--; | ||
| 1382 | + prev = next; | ||
| 1383 | + next = next->next; | ||
| 1384 | + } | ||
| 1385 | + model_add_to_worklist_at (insn, prev); | ||
| 1386 | +} | ||
| 1387 | + | ||
| 1388 | +/* INSN may now have a higher priority (in the model_order_p sense) | ||
| 1389 | + than before. Move it up the worklist if necessary. */ | ||
| 1390 | + | ||
| 1391 | +static void | ||
| 1392 | +model_promote_insn (struct model_insn_info *insn) | ||
| 1393 | +{ | ||
| 1394 | + struct model_insn_info *prev; | ||
| 1395 | + int count; | ||
| 1396 | + | ||
| 1397 | + prev = insn->prev; | ||
| 1398 | + count = MAX_SCHED_READY_INSNS; | ||
| 1399 | + while (count > 0 && prev && model_order_p (insn, prev)) | ||
| 1400 | + { | ||
| 1401 | + count--; | ||
| 1402 | + prev = prev->prev; | ||
| 1403 | + } | ||
| 1404 | + if (prev != insn->prev) | ||
| 1405 | + { | ||
| 1406 | + model_remove_from_worklist (insn); | ||
| 1407 | + model_add_to_worklist_at (insn, prev); | ||
| 1408 | + } | ||
| 1409 | +} | ||
| 1410 | + | ||
| 1411 | +/* Add INSN to the end of the model schedule. */ | ||
| 1412 | + | ||
| 1413 | +static void | ||
| 1414 | +model_add_to_schedule (rtx insn) | ||
| 1415 | +{ | ||
| 1416 | + unsigned int point; | ||
| 1417 | + | ||
| 1418 | + gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE); | ||
| 1419 | + QUEUE_INDEX (insn) = QUEUE_SCHEDULED; | ||
| 1420 | + | ||
| 1421 | + point = VEC_length (rtx, model_schedule); | ||
| 1422 | + VEC_quick_push (rtx, model_schedule, insn); | ||
| 1423 | + INSN_MODEL_INDEX (insn) = point + 1; | ||
| 1424 | +} | ||
| 1425 | + | ||
| 1426 | +/* Analyze the instructions that are to be scheduled, setting up | ||
| 1427 | + MODEL_INSN_INFO (...) and model_num_insns accordingly. Add ready | ||
| 1428 | + instructions to model_worklist. */ | ||
| 1429 | + | ||
| 1430 | +static void | ||
| 1431 | +model_analyze_insns (void) | ||
| 1432 | +{ | ||
| 1433 | + rtx start, end, iter; | ||
| 1434 | + sd_iterator_def sd_it; | ||
| 1435 | + dep_t dep; | ||
| 1436 | + struct model_insn_info *insn, *con; | ||
| 1437 | + | ||
| 1438 | + model_num_insns = 0; | ||
| 1439 | + start = PREV_INSN (current_sched_info->next_tail); | ||
| 1440 | + end = current_sched_info->prev_head; | ||
| 1441 | + for (iter = start; iter != end; iter = PREV_INSN (iter)) | ||
| 1442 | + if (NONDEBUG_INSN_P (iter)) | ||
| 1443 | + { | ||
| 1444 | + insn = MODEL_INSN_INFO (iter); | ||
| 1445 | + insn->insn = iter; | ||
| 1446 | + FOR_EACH_DEP (iter, SD_LIST_FORW, sd_it, dep) | ||
| 1447 | + { | ||
| 1448 | + con = MODEL_INSN_INFO (DEP_CON (dep)); | ||
| 1449 | + if (con->insn && insn->alap < con->alap + 1) | ||
| 1450 | + insn->alap = con->alap + 1; | ||
| 1451 | + } | ||
| 1452 | + | ||
| 1453 | + insn->old_queue = QUEUE_INDEX (iter); | ||
| 1454 | + QUEUE_INDEX (iter) = QUEUE_NOWHERE; | ||
| 1455 | + | ||
| 1456 | + insn->unscheduled_preds = dep_list_size (iter, SD_LIST_HARD_BACK); | ||
| 1457 | + if (insn->unscheduled_preds == 0) | ||
| 1458 | + model_add_to_worklist (insn, NULL, model_worklist); | ||
| 1459 | + | ||
| 1460 | + model_num_insns++; | ||
| 1461 | + } | ||
| 1462 | +} | ||
| 1463 | + | ||
| 1464 | +/* The global state describes the register pressure at the start of the | ||
| 1465 | + model schedule. Initialize GROUP accordingly. */ | ||
| 1466 | + | ||
| 1467 | +static void | ||
| 1468 | +model_init_pressure_group (struct model_pressure_group *group) | ||
| 1469 | +{ | ||
| 1470 | + int cci, cl; | ||
| 1471 | + | ||
| 1472 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1473 | + { | ||
| 1474 | + cl = ira_reg_class_cover[cci]; | ||
| 1475 | + group->limits[cci].pressure = curr_reg_pressure[cl]; | ||
| 1476 | + group->limits[cci].point = 0; | ||
| 1477 | + } | ||
| 1478 | + /* Use index model_num_insns to record the state after the last | ||
| 1479 | + instruction in the model schedule. */ | ||
| 1480 | + group->model = XNEWVEC (struct model_pressure_data, | ||
| 1481 | + (model_num_insns + 1) * ira_reg_class_cover_size); | ||
| 1482 | +} | ||
| 1483 | + | ||
| 1484 | +/* Record that MODEL_REF_PRESSURE (GROUP, POINT, CCI) is PRESSURE. | ||
| 1485 | + Update the maximum pressure for the whole schedule. */ | ||
| 1486 | + | ||
| 1487 | +static void | ||
| 1488 | +model_record_pressure (struct model_pressure_group *group, | ||
| 1489 | + int point, int cci, int pressure) | ||
| 1490 | +{ | ||
| 1491 | + MODEL_REF_PRESSURE (group, point, cci) = pressure; | ||
| 1492 | + if (group->limits[cci].pressure < pressure) | ||
| 1493 | + { | ||
| 1494 | + group->limits[cci].pressure = pressure; | ||
| 1495 | + group->limits[cci].point = point; | ||
| 1496 | + } | ||
| 1497 | +} | ||
| 1498 | + | ||
| 1499 | +/* INSN has just been added to the end of the model schedule. Record its | ||
| 1500 | + register-pressure information. */ | ||
| 1501 | + | ||
| 1502 | +static void | ||
| 1503 | +model_record_pressures (struct model_insn_info *insn) | ||
| 1504 | +{ | ||
| 1505 | + struct reg_pressure_data *reg_pressure; | ||
| 1506 | + int point, cci, cl, delta; | ||
| 1507 | + int death[N_REG_CLASSES]; | ||
| 1508 | + | ||
| 1509 | + point = model_index (insn->insn); | ||
| 1510 | + if (sched_verbose >= 2) | ||
| 1511 | + { | ||
| 1512 | + char buf[2048]; | ||
| 1513 | + | ||
| 1514 | + if (point == 0) | ||
| 1515 | + { | ||
| 1516 | + fprintf (sched_dump, "\n;;\tModel schedule:\n;;\n"); | ||
| 1517 | + fprintf (sched_dump, ";;\t| idx insn | mpri hght dpth prio |\n"); | ||
| 1518 | + } | ||
| 1519 | + print_pattern (buf, PATTERN (insn->insn), 0); | ||
| 1520 | + fprintf (sched_dump, ";;\t| %3d %4d | %4d %4d %4d %4d | %-30s ", | ||
| 1521 | + point, INSN_UID (insn->insn), insn->model_priority, | ||
| 1522 | + insn->depth + insn->alap, insn->depth, | ||
| 1523 | + INSN_PRIORITY (insn->insn), buf); | ||
| 1524 | + } | ||
| 1525 | + calculate_reg_deaths (insn->insn, death); | ||
| 1526 | + reg_pressure = INSN_REG_PRESSURE (insn->insn); | ||
| 1527 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1528 | + { | ||
| 1529 | + cl = ira_reg_class_cover[cci]; | ||
| 1530 | + delta = reg_pressure[cci].set_increase - death[cl]; | ||
| 1531 | + if (sched_verbose >= 2) | ||
| 1532 | + fprintf (sched_dump, " %s:[%d,%+d]", reg_class_names[cl], | ||
| 1533 | + curr_reg_pressure[cl], delta); | ||
| 1534 | + model_record_pressure (&model_before_pressure, point, cci, | ||
| 1535 | + curr_reg_pressure[cl]); | ||
| 1536 | + } | ||
| 1537 | + if (sched_verbose >= 2) | ||
| 1538 | + fprintf (sched_dump, "\n"); | ||
| 1539 | +} | ||
| 1540 | + | ||
| 1541 | +/* All instructions have been added to the model schedule. Record the | ||
| 1542 | + final register pressure in GROUP and set up all MODEL_MAX_PRESSUREs. */ | ||
| 1543 | + | ||
| 1544 | +static void | ||
| 1545 | +model_record_final_pressures (struct model_pressure_group *group) | ||
| 1546 | +{ | ||
| 1547 | + int point, cci, max_pressure, ref_pressure, cl; | ||
| 1548 | + | ||
| 1549 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1550 | + { | ||
| 1551 | + /* Record the final pressure for this class. */ | ||
| 1552 | + cl = ira_reg_class_cover[cci]; | ||
| 1553 | + point = model_num_insns; | ||
| 1554 | + ref_pressure = curr_reg_pressure[cl]; | ||
| 1555 | + model_record_pressure (group, point, cci, ref_pressure); | ||
| 1556 | + | ||
| 1557 | + /* Record the original maximum pressure. */ | ||
| 1558 | + group->limits[cci].orig_pressure = group->limits[cci].pressure; | ||
| 1559 | + | ||
| 1560 | + /* Update the MODEL_MAX_PRESSURE for every point of the schedule. */ | ||
| 1561 | + max_pressure = ref_pressure; | ||
| 1562 | + MODEL_MAX_PRESSURE (group, point, cci) = max_pressure; | ||
| 1563 | + while (point > 0) | ||
| 1564 | + { | ||
| 1565 | + point--; | ||
| 1566 | + ref_pressure = MODEL_REF_PRESSURE (group, point, cci); | ||
| 1567 | + max_pressure = MAX (max_pressure, ref_pressure); | ||
| 1568 | + MODEL_MAX_PRESSURE (group, point, cci) = max_pressure; | ||
| 1569 | + } | ||
| 1570 | + } | ||
| 1571 | +} | ||
| 1572 | + | ||
| 1573 | +/* Update all successors of INSN, given that INSN has just been scheduled. */ | ||
| 1574 | + | ||
| 1575 | +static void | ||
| 1576 | +model_add_successors_to_worklist (struct model_insn_info *insn) | ||
| 1577 | +{ | ||
| 1578 | + sd_iterator_def sd_it; | ||
| 1579 | + struct model_insn_info *con; | ||
| 1580 | + dep_t dep; | ||
| 1581 | + | ||
| 1582 | + FOR_EACH_DEP (insn->insn, SD_LIST_FORW, sd_it, dep) | ||
| 1583 | + { | ||
| 1584 | + con = MODEL_INSN_INFO (DEP_CON (dep)); | ||
| 1585 | + /* Ignore debug instructions, and instructions from other blocks. */ | ||
| 1586 | + if (con->insn) | ||
| 1587 | + { | ||
| 1588 | + con->unscheduled_preds--; | ||
| 1589 | + | ||
| 1590 | + /* Update the depth field of each true-dependent successor. | ||
| 1591 | + Increasing the depth gives them a higher priority than | ||
| 1592 | + before. */ | ||
| 1593 | + if (DEP_TYPE (dep) == REG_DEP_TRUE && con->depth < insn->depth + 1) | ||
| 1594 | + { | ||
| 1595 | + con->depth = insn->depth + 1; | ||
| 1596 | + if (QUEUE_INDEX (con->insn) == QUEUE_READY) | ||
| 1597 | + model_promote_insn (con); | ||
| 1598 | + } | ||
| 1599 | + | ||
| 1600 | + /* If this is a true dependency, or if there are no remaining | ||
| 1601 | + dependencies for CON (meaning that CON only had non-true | ||
| 1602 | + dependencies), make sure that CON is on the worklist. | ||
| 1603 | + We don't bother otherwise because it would tend to fill the | ||
| 1604 | + worklist with a lot of low-priority instructions that are not | ||
| 1605 | + yet ready to issue. */ | ||
| 1606 | + if ((con->depth > 0 || con->unscheduled_preds == 0) | ||
| 1607 | + && QUEUE_INDEX (con->insn) == QUEUE_NOWHERE) | ||
| 1608 | + model_add_to_worklist (con, insn, insn->next); | ||
| 1609 | + } | ||
| 1610 | + } | ||
| 1611 | +} | ||
| 1612 | + | ||
| 1613 | +/* Give INSN a higher priority than any current instruction, then give | ||
| 1614 | + unscheduled predecessors of INSN a higher priority still. If any of | ||
| 1615 | + those predecessors are not on the model worklist, do the same for its | ||
| 1616 | + predecessors, and so on. */ | ||
| 1617 | + | ||
| 1618 | +static void | ||
| 1619 | +model_promote_predecessors (struct model_insn_info *insn) | ||
| 1620 | +{ | ||
| 1621 | + struct model_insn_info *pro, *first; | ||
| 1622 | + sd_iterator_def sd_it; | ||
| 1623 | + dep_t dep; | ||
| 1624 | + | ||
| 1625 | + if (sched_verbose >= 7) | ||
| 1626 | + fprintf (sched_dump, ";;\t+--- priority of %d = %d, priority of", | ||
| 1627 | + INSN_UID (insn->insn), model_next_priority); | ||
| 1628 | + insn->model_priority = model_next_priority++; | ||
| 1629 | + model_remove_from_worklist (insn); | ||
| 1630 | + model_add_to_worklist_at (insn, NULL); | ||
| 1631 | + | ||
| 1632 | + first = NULL; | ||
| 1633 | + for (;;) | ||
| 1634 | + { | ||
| 1635 | + FOR_EACH_DEP (insn->insn, SD_LIST_HARD_BACK, sd_it, dep) | ||
| 1636 | + { | ||
| 1637 | + pro = MODEL_INSN_INFO (DEP_PRO (dep)); | ||
| 1638 | + /* The first test is to ignore debug instructions, and instructions | ||
| 1639 | + from other blocks. */ | ||
| 1640 | + if (pro->insn | ||
| 1641 | + && pro->model_priority != model_next_priority | ||
| 1642 | + && QUEUE_INDEX (pro->insn) != QUEUE_SCHEDULED) | ||
| 1643 | + { | ||
| 1644 | + pro->model_priority = model_next_priority; | ||
| 1645 | + if (sched_verbose >= 7) | ||
| 1646 | + fprintf (sched_dump, " %d", INSN_UID (pro->insn)); | ||
| 1647 | + if (QUEUE_INDEX (pro->insn) == QUEUE_READY) | ||
| 1648 | + { | ||
| 1649 | + /* PRO is already in the worklist, but it now has | ||
| 1650 | + a higher priority than before. Move it at the | ||
| 1651 | + appropriate place. */ | ||
| 1652 | + model_remove_from_worklist (pro); | ||
| 1653 | + model_add_to_worklist (pro, NULL, model_worklist); | ||
| 1654 | + } | ||
| 1655 | + else | ||
| 1656 | + { | ||
| 1657 | + /* PRO isn't in the worklist. Recursively process | ||
| 1658 | + its predecessors until we find one that is. */ | ||
| 1659 | + pro->next = first; | ||
| 1660 | + first = pro; | ||
| 1661 | + } | ||
| 1662 | + } | ||
| 1663 | + } | ||
| 1664 | + if (!first) | ||
| 1665 | + break; | ||
| 1666 | + insn = first; | ||
| 1667 | + first = insn->next; | ||
| 1668 | + } | ||
| 1669 | + if (sched_verbose >= 7) | ||
| 1670 | + fprintf (sched_dump, " = %d\n", model_next_priority); | ||
| 1671 | + model_next_priority++; | ||
| 1672 | +} | ||
| 1673 | + | ||
| 1674 | +/* Pick one instruction from model_worklist and process it. */ | ||
| 1675 | + | ||
| 1676 | +static void | ||
| 1677 | +model_choose_insn (void) | ||
| 1678 | +{ | ||
| 1679 | + struct model_insn_info *insn, *fallback; | ||
| 1680 | + int count; | ||
| 1681 | + | ||
| 1682 | + if (sched_verbose >= 7) | ||
| 1683 | + { | ||
| 1684 | + fprintf (sched_dump, ";;\t+--- worklist:\n"); | ||
| 1685 | + insn = model_worklist; | ||
| 1686 | + count = MAX_SCHED_READY_INSNS; | ||
| 1687 | + while (count > 0 && insn) | ||
| 1688 | + { | ||
| 1689 | + fprintf (sched_dump, ";;\t+--- %d [%d, %d, %d, %d]\n", | ||
| 1690 | + INSN_UID (insn->insn), insn->model_priority, | ||
| 1691 | + insn->depth + insn->alap, insn->depth, | ||
| 1692 | + INSN_PRIORITY (insn->insn)); | ||
| 1693 | + count--; | ||
| 1694 | + insn = insn->next; | ||
| 1695 | + } | ||
| 1696 | + } | ||
| 1697 | + | ||
| 1698 | + /* Look for a ready instruction whose model_classify_priority is zero | ||
| 1699 | + or negative, picking the highest-priority one. Adding such an | ||
| 1700 | + instruction to the schedule now should do no harm, and may actually | ||
| 1701 | + do some good. | ||
| 1702 | + | ||
| 1703 | + Failing that, see whether there is an instruction with the highest | ||
| 1704 | + extant model_priority that is not yet ready, but which would reduce | ||
| 1705 | + pressure if it became ready. This is designed to catch cases like: | ||
| 1706 | + | ||
| 1707 | + (set (mem (reg R1)) (reg R2)) | ||
| 1708 | + | ||
| 1709 | + where the instruction is the last remaining use of R1 and where the | ||
| 1710 | + value of R2 is not yet available (or vice versa). The death of R1 | ||
| 1711 | + means that this instruction already reduces pressure. It is of | ||
| 1712 | + course possible that the computation of R2 involves other registers | ||
| 1713 | + that are hard to kill, but such cases are rare enough for this | ||
| 1714 | + heuristic to be a win in general. | ||
| 1715 | + | ||
| 1716 | + Failing that, just pick the highest-priority instruction in the | ||
| 1717 | + worklist. */ | ||
| 1718 | + count = MAX_SCHED_READY_INSNS; | ||
| 1719 | + insn = model_worklist; | ||
| 1720 | + fallback = 0; | ||
| 1721 | + for (;;) | ||
| 1722 | + { | ||
| 1723 | + if (count == 0 || !insn) | ||
| 1724 | + { | ||
| 1725 | + insn = fallback ? fallback : model_worklist; | ||
| 1726 | + break; | ||
| 1727 | + } | ||
| 1728 | + if (insn->unscheduled_preds) | ||
| 1729 | + { | ||
| 1730 | + if (model_worklist->model_priority == insn->model_priority | ||
| 1731 | + && !fallback | ||
| 1732 | + && model_classify_pressure (insn) < 0) | ||
| 1733 | + fallback = insn; | ||
| 1734 | + } | ||
| 1735 | + else | ||
| 1736 | + { | ||
| 1737 | + if (model_classify_pressure (insn) <= 0) | ||
| 1738 | + break; | ||
| 1739 | + } | ||
| 1740 | + count--; | ||
| 1741 | + insn = insn->next; | ||
| 1742 | + } | ||
| 1743 | + | ||
| 1744 | + if (sched_verbose >= 7 && insn != model_worklist) | ||
| 1745 | + { | ||
| 1746 | + if (insn->unscheduled_preds) | ||
| 1747 | + fprintf (sched_dump, ";;\t+--- promoting insn %d, with dependencies\n", | ||
| 1748 | + INSN_UID (insn->insn)); | ||
| 1749 | + else | ||
| 1750 | + fprintf (sched_dump, ";;\t+--- promoting insn %d, which is ready\n", | ||
| 1751 | + INSN_UID (insn->insn)); | ||
| 1752 | + } | ||
| 1753 | + if (insn->unscheduled_preds) | ||
| 1754 | + /* INSN isn't yet ready to issue. Give all its predecessors the | ||
| 1755 | + highest priority. */ | ||
| 1756 | + model_promote_predecessors (insn); | ||
| 1757 | + else | ||
| 1758 | + { | ||
| 1759 | + /* INSN is ready. Add it to the end of model_schedule and | ||
| 1760 | + process its successors. */ | ||
| 1761 | + model_add_successors_to_worklist (insn); | ||
| 1762 | + model_remove_from_worklist (insn); | ||
| 1763 | + model_add_to_schedule (insn->insn); | ||
| 1764 | + model_record_pressures (insn); | ||
| 1765 | + update_register_pressure (insn->insn); | ||
| 1766 | + } | ||
| 1767 | +} | ||
| 1768 | + | ||
| 1769 | +/* Restore all QUEUE_INDEXs to the values that they had before | ||
| 1770 | + model_start_schedule was called. */ | ||
| 1771 | + | ||
| 1772 | +static void | ||
| 1773 | +model_reset_queue_indices (void) | ||
| 1774 | +{ | ||
| 1775 | + unsigned int i; | ||
| 1776 | + rtx insn; | ||
| 1777 | + | ||
| 1778 | + FOR_EACH_VEC_ELT (rtx, model_schedule, i, insn) | ||
| 1779 | + QUEUE_INDEX (insn) = MODEL_INSN_INFO (insn)->old_queue; | ||
| 1780 | +} | ||
| 1781 | + | ||
| 1782 | +/* We have calculated the model schedule and spill costs. Print a summary | ||
| 1783 | + to sched_dump. */ | ||
| 1784 | + | ||
| 1785 | +static void | ||
| 1786 | +model_dump_pressure_summary (void) | ||
| 1787 | +{ | ||
| 1788 | + int cci, cl; | ||
| 1789 | + | ||
| 1790 | + fprintf (sched_dump, ";; Pressure summary:"); | ||
| 1791 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
| 1792 | + { | ||
| 1793 | + cl = ira_reg_class_cover[cci]; | ||
| 1794 | + fprintf (sched_dump, " %s:%d", reg_class_names[cl], | ||
| 1795 | + model_before_pressure.limits[cci].pressure); | ||
| 1796 | + } | ||
| 1797 | + fprintf (sched_dump, "\n\n"); | ||
| 1798 | +} | ||
| 1799 | + | ||
| 1800 | +/* Initialize the SCHED_PRESSURE_MODEL information for the current | ||
| 1801 | + scheduling region. */ | ||
| 1802 | + | ||
| 1803 | +static void | ||
| 1804 | +model_start_schedule (void) | ||
| 1805 | +{ | ||
| 1806 | + basic_block bb; | ||
| 1807 | + | ||
| 1808 | + model_next_priority = 1; | ||
| 1809 | + model_schedule = VEC_alloc (rtx, heap, sched_max_luid); | ||
| 1810 | + model_insns = XCNEWVEC (struct model_insn_info, sched_max_luid); | ||
| 1811 | + | ||
| 1812 | + bb = BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head)); | ||
| 1813 | + initiate_reg_pressure_info (df_get_live_in (bb)); | ||
| 1814 | + | ||
| 1815 | + model_analyze_insns (); | ||
| 1816 | + model_init_pressure_group (&model_before_pressure); | ||
| 1817 | + while (model_worklist) | ||
| 1818 | + model_choose_insn (); | ||
| 1819 | + gcc_assert (model_num_insns == (int) VEC_length (rtx, model_schedule)); | ||
| 1820 | + if (sched_verbose >= 2) | ||
| 1821 | + fprintf (sched_dump, "\n"); | ||
| 1822 | + | ||
| 1823 | + model_record_final_pressures (&model_before_pressure); | ||
| 1824 | + model_reset_queue_indices (); | ||
| 1825 | + | ||
| 1826 | + XDELETEVEC (model_insns); | ||
| 1827 | + | ||
| 1828 | + model_curr_point = 0; | ||
| 1829 | + initiate_reg_pressure_info (df_get_live_in (bb)); | ||
| 1830 | + if (sched_verbose >= 1) | ||
| 1831 | + model_dump_pressure_summary (); | ||
| 1832 | +} | ||
| 1833 | + | ||
| 1834 | +/* Free the information associated with GROUP. */ | ||
| 1835 | + | ||
| 1836 | +static void | ||
| 1837 | +model_finalize_pressure_group (struct model_pressure_group *group) | ||
| 1838 | +{ | ||
| 1839 | + XDELETEVEC (group->model); | ||
| 1840 | +} | ||
| 1841 | + | ||
| 1842 | +/* Free the information created by model_start_schedule. */ | ||
| 1843 | + | ||
| 1844 | +static void | ||
| 1845 | +model_end_schedule (void) | ||
| 1846 | +{ | ||
| 1847 | + model_finalize_pressure_group (&model_before_pressure); | ||
| 1848 | + VEC_free (rtx, heap, model_schedule); | ||
| 1849 | +} | ||
| 1850 | + | ||
| 1851 | /* INSN is the "currently executing insn". Launch each insn which was | ||
| 1852 | waiting on INSN. READY is the ready list which contains the insns | ||
| 1853 | that are ready to fire. CLOCK is the current cycle. The function | ||
| 1854 | @@ -1667,10 +3065,14 @@ | ||
| 1855 | reg_class_names[ira_reg_class_cover[i]], | ||
| 1856 | pressure_info[i].set_increase, pressure_info[i].change); | ||
| 1857 | } | ||
| 1858 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
| 1859 | + && model_curr_point < model_num_insns | ||
| 1860 | + && model_index (insn) == model_curr_point) | ||
| 1861 | + fprintf (sched_dump, ":model %d", model_curr_point); | ||
| 1862 | fputc ('\n', sched_dump); | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | - if (sched_pressure_p && !DEBUG_INSN_P (insn)) | ||
| 1866 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED && !DEBUG_INSN_P (insn)) | ||
| 1867 | update_reg_and_insn_max_reg_pressure (insn); | ||
| 1868 | |||
| 1869 | /* Scheduling instruction should have all its dependencies resolved and | ||
| 1870 | @@ -1728,6 +3130,24 @@ | ||
| 1871 | gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE); | ||
| 1872 | QUEUE_INDEX (insn) = QUEUE_SCHEDULED; | ||
| 1873 | |||
| 1874 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
| 1875 | + && model_curr_point < model_num_insns | ||
| 1876 | + && NONDEBUG_INSN_P (insn)) | ||
| 1877 | + { | ||
| 1878 | + if (model_index (insn) == model_curr_point) | ||
| 1879 | + do | ||
| 1880 | + model_curr_point++; | ||
| 1881 | + while (model_curr_point < model_num_insns | ||
| 1882 | + && (QUEUE_INDEX (MODEL_INSN (model_curr_point)) | ||
| 1883 | + == QUEUE_SCHEDULED)); | ||
| 1884 | + else | ||
| 1885 | + model_recompute (insn); | ||
| 1886 | + model_update_limit_points (); | ||
| 1887 | + update_register_pressure (insn); | ||
| 1888 | + if (sched_verbose >= 2) | ||
| 1889 | + print_curr_reg_pressure (); | ||
| 1890 | + } | ||
| 1891 | + | ||
| 1892 | gcc_assert (INSN_TICK (insn) >= MIN_TICK); | ||
| 1893 | if (INSN_TICK (insn) > clock_var) | ||
| 1894 | /* INSN has been prematurely moved from the queue to the ready list. | ||
| 1895 | @@ -2056,7 +3476,16 @@ | ||
| 1896 | /* If the ready list is full, delay the insn for 1 cycle. | ||
| 1897 | See the comment in schedule_block for the rationale. */ | ||
| 1898 | if (!reload_completed | ||
| 1899 | - && ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS | ||
| 1900 | + && (ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS | ||
| 1901 | + || (sched_pressure == SCHED_PRESSURE_MODEL | ||
| 1902 | + /* Limit pressure recalculations to MAX_SCHED_READY_INSNS | ||
| 1903 | + instructions too. */ | ||
| 1904 | + && model_index (insn) > (model_curr_point | ||
| 1905 | + + MAX_SCHED_READY_INSNS))) | ||
| 1906 | + && !(sched_pressure == SCHED_PRESSURE_MODEL | ||
| 1907 | + && model_curr_point < model_num_insns | ||
| 1908 | + /* Always allow the next model instruction to issue. */ | ||
| 1909 | + && model_index (insn) == model_curr_point) | ||
| 1910 | && !SCHED_GROUP_P (insn) | ||
| 1911 | && insn != skip_insn) | ||
| 1912 | { | ||
| 1913 | @@ -2293,12 +3722,12 @@ | ||
| 1914 | fprintf (sched_dump, " %s:%d", | ||
| 1915 | (*current_sched_info->print_insn) (p[i], 0), | ||
| 1916 | INSN_LUID (p[i])); | ||
| 1917 | - if (sched_pressure_p) | ||
| 1918 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 1919 | fprintf (sched_dump, "(cost=%d", | ||
| 1920 | INSN_REG_PRESSURE_EXCESS_COST_CHANGE (p[i])); | ||
| 1921 | if (INSN_TICK (p[i]) > clock_var) | ||
| 1922 | fprintf (sched_dump, ":delay=%d", INSN_TICK (p[i]) - clock_var); | ||
| 1923 | - if (sched_pressure_p) | ||
| 1924 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 1925 | fprintf (sched_dump, ")"); | ||
| 1926 | } | ||
| 1927 | fprintf (sched_dump, "\n"); | ||
| 1928 | @@ -2609,8 +4038,8 @@ | ||
| 1929 | { | ||
| 1930 | if (state_dead_lock_p (state) | ||
| 1931 | || insn_finishes_cycle_p (insn)) | ||
| 1932 | - /* We won't issue any more instructions in the next | ||
| 1933 | - choice_state. */ | ||
| 1934 | + /* We won't issue any more instructions in the next | ||
| 1935 | + choice_state. */ | ||
| 1936 | top->rest = 0; | ||
| 1937 | else | ||
| 1938 | top->rest--; | ||
| 1939 | @@ -2813,6 +4242,59 @@ | ||
| 1940 | } | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | +/* Examine all insns on the ready list and queue those which can't be | ||
| 1944 | + issued in this cycle. TEMP_STATE is temporary scheduler state we | ||
| 1945 | + can use as scratch space. If FIRST_CYCLE_INSN_P is true, no insns | ||
| 1946 | + have been issued for the current cycle, which means it is valid to | ||
| 1947 | + issue an asm statement. */ | ||
| 1948 | + | ||
| 1949 | +static void | ||
| 1950 | +prune_ready_list (state_t temp_state, bool first_cycle_insn_p) | ||
| 1951 | +{ | ||
| 1952 | + int i; | ||
| 1953 | + | ||
| 1954 | + restart: | ||
| 1955 | + for (i = 0; i < ready.n_ready; i++) | ||
| 1956 | + { | ||
| 1957 | + rtx insn = ready_element (&ready, i); | ||
| 1958 | + int cost = 0; | ||
| 1959 | + | ||
| 1960 | + if (recog_memoized (insn) < 0) | ||
| 1961 | + { | ||
| 1962 | + if (!first_cycle_insn_p | ||
| 1963 | + && (GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
| 1964 | + || asm_noperands (PATTERN (insn)) >= 0)) | ||
| 1965 | + cost = 1; | ||
| 1966 | + } | ||
| 1967 | + else if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 1968 | + { | ||
| 1969 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
| 1970 | + && INSN_TICK (insn) <= clock_var) | ||
| 1971 | + { | ||
| 1972 | + memcpy (temp_state, curr_state, dfa_state_size); | ||
| 1973 | + if (state_transition (temp_state, insn) >= 0) | ||
| 1974 | + INSN_TICK (insn) = clock_var + 1; | ||
| 1975 | + } | ||
| 1976 | + cost = 0; | ||
| 1977 | + } | ||
| 1978 | + else | ||
| 1979 | + { | ||
| 1980 | + memcpy (temp_state, curr_state, dfa_state_size); | ||
| 1981 | + cost = state_transition (temp_state, insn); | ||
| 1982 | + if (cost < 0) | ||
| 1983 | + cost = 0; | ||
| 1984 | + else if (cost == 0) | ||
| 1985 | + cost = 1; | ||
| 1986 | + } | ||
| 1987 | + if (cost >= 1) | ||
| 1988 | + { | ||
| 1989 | + ready_remove (&ready, i); | ||
| 1990 | + queue_insn (insn, cost); | ||
| 1991 | + goto restart; | ||
| 1992 | + } | ||
| 1993 | + } | ||
| 1994 | +} | ||
| 1995 | + | ||
| 1996 | /* Use forward list scheduling to rearrange insns of block pointed to by | ||
| 1997 | TARGET_BB, possibly bringing insns from subsequent blocks in the same | ||
| 1998 | region. */ | ||
| 1999 | @@ -2882,6 +4364,9 @@ | ||
| 2000 | in try_ready () (which is called through init_ready_list ()). */ | ||
| 2001 | (*current_sched_info->init_ready_list) (); | ||
| 2002 | |||
| 2003 | + if (sched_pressure == SCHED_PRESSURE_MODEL) | ||
| 2004 | + model_start_schedule (); | ||
| 2005 | + | ||
| 2006 | /* The algorithm is O(n^2) in the number of ready insns at any given | ||
| 2007 | time in the worst case. Before reload we are more likely to have | ||
| 2008 | big lists so truncate them to a reasonable size. */ | ||
| 2009 | @@ -2963,6 +4448,10 @@ | ||
| 2010 | } | ||
| 2011 | while (advance > 0); | ||
| 2012 | |||
| 2013 | + prune_ready_list (temp_state, true); | ||
| 2014 | + if (ready.n_ready == 0) | ||
| 2015 | + continue; | ||
| 2016 | + | ||
| 2017 | if (sort_p) | ||
| 2018 | { | ||
| 2019 | /* Sort the ready list based on priority. */ | ||
| 2020 | @@ -3040,7 +4529,7 @@ | ||
| 2021 | fprintf (sched_dump, ";;\tReady list (t = %3d): ", | ||
| 2022 | clock_var); | ||
| 2023 | debug_ready_list (&ready); | ||
| 2024 | - if (sched_pressure_p) | ||
| 2025 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
| 2026 | print_curr_reg_pressure (); | ||
| 2027 | } | ||
| 2028 | |||
| 2029 | @@ -3084,7 +4573,8 @@ | ||
| 2030 | else | ||
| 2031 | insn = ready_remove_first (&ready); | ||
| 2032 | |||
| 2033 | - if (sched_pressure_p && INSN_TICK (insn) > clock_var) | ||
| 2034 | + if (sched_pressure != SCHED_PRESSURE_NONE | ||
| 2035 | + && INSN_TICK (insn) > clock_var) | ||
| 2036 | { | ||
| 2037 | ready_add (&ready, insn, true); | ||
| 2038 | advance = 1; | ||
| 2039 | @@ -3112,44 +4602,6 @@ | ||
| 2040 | } | ||
| 2041 | |||
| 2042 | sort_p = TRUE; | ||
| 2043 | - memcpy (temp_state, curr_state, dfa_state_size); | ||
| 2044 | - if (recog_memoized (insn) < 0) | ||
| 2045 | - { | ||
| 2046 | - asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
| 2047 | - || asm_noperands (PATTERN (insn)) >= 0); | ||
| 2048 | - if (!first_cycle_insn_p && asm_p) | ||
| 2049 | - /* This is asm insn which is tried to be issued on the | ||
| 2050 | - cycle not first. Issue it on the next cycle. */ | ||
| 2051 | - cost = 1; | ||
| 2052 | - else | ||
| 2053 | - /* A USE insn, or something else we don't need to | ||
| 2054 | - understand. We can't pass these directly to | ||
| 2055 | - state_transition because it will trigger a | ||
| 2056 | - fatal error for unrecognizable insns. */ | ||
| 2057 | - cost = 0; | ||
| 2058 | - } | ||
| 2059 | - else if (sched_pressure_p) | ||
| 2060 | - cost = 0; | ||
| 2061 | - else | ||
| 2062 | - { | ||
| 2063 | - cost = state_transition (temp_state, insn); | ||
| 2064 | - if (cost < 0) | ||
| 2065 | - cost = 0; | ||
| 2066 | - else if (cost == 0) | ||
| 2067 | - cost = 1; | ||
| 2068 | - } | ||
| 2069 | - | ||
| 2070 | - if (cost >= 1) | ||
| 2071 | - { | ||
| 2072 | - queue_insn (insn, cost); | ||
| 2073 | - if (SCHED_GROUP_P (insn)) | ||
| 2074 | - { | ||
| 2075 | - advance = cost; | ||
| 2076 | - break; | ||
| 2077 | - } | ||
| 2078 | - | ||
| 2079 | - continue; | ||
| 2080 | - } | ||
| 2081 | |||
| 2082 | if (current_sched_info->can_schedule_ready_p | ||
| 2083 | && ! (*current_sched_info->can_schedule_ready_p) (insn)) | ||
| 2084 | @@ -3200,11 +4652,17 @@ | ||
| 2085 | reemit_notes (insn); | ||
| 2086 | last_scheduled_insn = insn; | ||
| 2087 | |||
| 2088 | - if (memcmp (curr_state, temp_state, dfa_state_size) != 0) | ||
| 2089 | - { | ||
| 2090 | - cycle_issued_insns++; | ||
| 2091 | - memcpy (curr_state, temp_state, dfa_state_size); | ||
| 2092 | - } | ||
| 2093 | + if (recog_memoized (insn) >= 0) | ||
| 2094 | + { | ||
| 2095 | + cost = state_transition (curr_state, insn); | ||
| 2096 | + if (sched_pressure != SCHED_PRESSURE_WEIGHTED) | ||
| 2097 | + gcc_assert (cost < 0); | ||
| 2098 | + cycle_issued_insns++; | ||
| 2099 | + asm_p = false; | ||
| 2100 | + } | ||
| 2101 | + else | ||
| 2102 | + asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
| 2103 | + || asm_noperands (PATTERN (insn)) >= 0); | ||
| 2104 | |||
| 2105 | if (targetm.sched.variable_issue) | ||
| 2106 | can_issue_more = | ||
| 2107 | @@ -3225,6 +4683,9 @@ | ||
| 2108 | |||
| 2109 | first_cycle_insn_p = false; | ||
| 2110 | |||
| 2111 | + if (ready.n_ready > 0) | ||
| 2112 | + prune_ready_list (temp_state, false); | ||
| 2113 | + | ||
| 2114 | /* Sort the ready list based on priority. This must be | ||
| 2115 | redone here, as schedule_insn may have readied additional | ||
| 2116 | insns that will not be sorted correctly. */ | ||
| 2117 | @@ -3321,6 +4782,9 @@ | ||
| 2118 | } | ||
| 2119 | } | ||
| 2120 | |||
| 2121 | + if (sched_pressure == SCHED_PRESSURE_MODEL) | ||
| 2122 | + model_end_schedule (); | ||
| 2123 | + | ||
| 2124 | if (sched_verbose) | ||
| 2125 | fprintf (sched_dump, ";; total time = %d\n", clock_var); | ||
| 2126 | |||
| 2127 | @@ -3424,10 +4888,14 @@ | ||
| 2128 | if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON)) | ||
| 2129 | targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT); | ||
| 2130 | |||
| 2131 | - sched_pressure_p = (flag_sched_pressure && ! reload_completed | ||
| 2132 | - && common_sched_info->sched_pass_id == SCHED_RGN_PASS); | ||
| 2133 | + if (flag_sched_pressure | ||
| 2134 | + && !reload_completed | ||
| 2135 | + && common_sched_info->sched_pass_id == SCHED_RGN_PASS) | ||
| 2136 | + sched_pressure = flag_sched_pressure_algorithm; | ||
| 2137 | + else | ||
| 2138 | + sched_pressure = SCHED_PRESSURE_NONE; | ||
| 2139 | |||
| 2140 | - if (sched_pressure_p) | ||
| 2141 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 2142 | ira_setup_eliminable_regset (); | ||
| 2143 | |||
| 2144 | /* Initialize SPEC_INFO. */ | ||
| 2145 | @@ -3504,7 +4972,7 @@ | ||
| 2146 | if (targetm.sched.init_global) | ||
| 2147 | targetm.sched.init_global (sched_dump, sched_verbose, get_max_uid () + 1); | ||
| 2148 | |||
| 2149 | - if (sched_pressure_p) | ||
| 2150 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 2151 | { | ||
| 2152 | int i, max_regno = max_reg_num (); | ||
| 2153 | |||
| 2154 | @@ -3517,8 +4985,11 @@ | ||
| 2155 | ? ira_class_translate[REGNO_REG_CLASS (i)] | ||
| 2156 | : reg_cover_class (i)); | ||
| 2157 | curr_reg_live = BITMAP_ALLOC (NULL); | ||
| 2158 | - saved_reg_live = BITMAP_ALLOC (NULL); | ||
| 2159 | - region_ref_regs = BITMAP_ALLOC (NULL); | ||
| 2160 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
| 2161 | + { | ||
| 2162 | + saved_reg_live = BITMAP_ALLOC (NULL); | ||
| 2163 | + region_ref_regs = BITMAP_ALLOC (NULL); | ||
| 2164 | + } | ||
| 2165 | } | ||
| 2166 | |||
| 2167 | curr_state = xmalloc (dfa_state_size); | ||
| 2168 | @@ -3618,12 +5089,15 @@ | ||
| 2169 | sched_finish (void) | ||
| 2170 | { | ||
| 2171 | haifa_finish_h_i_d (); | ||
| 2172 | - if (sched_pressure_p) | ||
| 2173 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 2174 | { | ||
| 2175 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
| 2176 | + { | ||
| 2177 | + BITMAP_FREE (region_ref_regs); | ||
| 2178 | + BITMAP_FREE (saved_reg_live); | ||
| 2179 | + } | ||
| 2180 | + BITMAP_FREE (curr_reg_live); | ||
| 2181 | free (sched_regno_cover_class); | ||
| 2182 | - BITMAP_FREE (region_ref_regs); | ||
| 2183 | - BITMAP_FREE (saved_reg_live); | ||
| 2184 | - BITMAP_FREE (curr_reg_live); | ||
| 2185 | } | ||
| 2186 | free (curr_state); | ||
| 2187 | |||
| 2188 | @@ -3936,7 +5410,7 @@ | ||
| 2189 | INSN_TICK (next) = tick; | ||
| 2190 | |||
| 2191 | delay = tick - clock_var; | ||
| 2192 | - if (delay <= 0 || sched_pressure_p) | ||
| 2193 | + if (delay <= 0 || sched_pressure != SCHED_PRESSURE_NONE) | ||
| 2194 | delay = QUEUE_READY; | ||
| 2195 | |||
| 2196 | change_queue_index (next, delay); | ||
| 2197 | @@ -5185,7 +6659,7 @@ | ||
| 2198 | if (insn == jump) | ||
| 2199 | break; | ||
| 2200 | |||
| 2201 | - if (dep_list_size (insn) == 0) | ||
| 2202 | + if (dep_list_size (insn, SD_LIST_FORW) == 0) | ||
| 2203 | { | ||
| 2204 | dep_def _new_dep, *new_dep = &_new_dep; | ||
| 2205 | |||
| 2206 | @@ -5556,6 +7030,7 @@ | ||
| 2207 | |||
| 2208 | FOR_EACH_VEC_ELT (haifa_insn_data_def, h_i_d, i, data) | ||
| 2209 | { | ||
| 2210 | + free (data->max_reg_pressure); | ||
| 2211 | if (data->reg_pressure != NULL) | ||
| 2212 | free (data->reg_pressure); | ||
| 2213 | for (use = data->reg_use_list; use != NULL; use = next) | ||
| 2214 | |||
| 2215 | === modified file 'gcc/sched-deps.c' | ||
| 2216 | --- old/gcc/sched-deps.c 2011-12-08 13:33:58 +0000 | ||
| 2217 | +++ new/gcc/sched-deps.c 2012-02-08 23:39:45 +0000 | ||
| 2218 | @@ -450,7 +450,7 @@ | ||
| 2219 | static void add_dependence_list_and_free (struct deps_desc *, rtx, | ||
| 2220 | rtx *, int, enum reg_note); | ||
| 2221 | static void delete_all_dependences (rtx); | ||
| 2222 | -static void fixup_sched_groups (rtx); | ||
| 2223 | +static void chain_to_prev_insn (rtx); | ||
| 2224 | |||
| 2225 | static void flush_pending_lists (struct deps_desc *, rtx, int, int); | ||
| 2226 | static void sched_analyze_1 (struct deps_desc *, rtx, rtx); | ||
| 2227 | @@ -1490,7 +1490,7 @@ | ||
| 2228 | the previous nonnote insn. */ | ||
| 2229 | |||
| 2230 | static void | ||
| 2231 | -fixup_sched_groups (rtx insn) | ||
| 2232 | +chain_to_prev_insn (rtx insn) | ||
| 2233 | { | ||
| 2234 | sd_iterator_def sd_it; | ||
| 2235 | dep_t dep; | ||
| 2236 | @@ -1999,7 +1999,7 @@ | ||
| 2237 | static struct reg_pressure_data *pressure_info; | ||
| 2238 | rtx link; | ||
| 2239 | |||
| 2240 | - gcc_assert (sched_pressure_p); | ||
| 2241 | + gcc_assert (sched_pressure != SCHED_PRESSURE_NONE); | ||
| 2242 | |||
| 2243 | if (! INSN_P (insn)) | ||
| 2244 | return; | ||
| 2245 | @@ -2030,8 +2030,9 @@ | ||
| 2246 | len = sizeof (struct reg_pressure_data) * ira_reg_class_cover_size; | ||
| 2247 | pressure_info | ||
| 2248 | = INSN_REG_PRESSURE (insn) = (struct reg_pressure_data *) xmalloc (len); | ||
| 2249 | - INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_reg_class_cover_size | ||
| 2250 | - * sizeof (int), 1); | ||
| 2251 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
| 2252 | + INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_reg_class_cover_size | ||
| 2253 | + * sizeof (int), 1); | ||
| 2254 | for (i = 0; i < ira_reg_class_cover_size; i++) | ||
| 2255 | { | ||
| 2256 | cl = ira_reg_class_cover[i]; | ||
| 2257 | @@ -2775,7 +2776,7 @@ | ||
| 2258 | || (NONJUMP_INSN_P (insn) && control_flow_insn_p (insn))) | ||
| 2259 | reg_pending_barrier = MOVE_BARRIER; | ||
| 2260 | |||
| 2261 | - if (sched_pressure_p) | ||
| 2262 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
| 2263 | { | ||
| 2264 | setup_insn_reg_uses (deps, insn); | ||
| 2265 | setup_insn_reg_pressure_info (insn); | ||
| 2266 | @@ -3076,7 +3077,7 @@ | ||
| 2267 | instructions that follow seem like they should be part | ||
| 2268 | of the call group. | ||
| 2269 | |||
| 2270 | - Also, if we did, fixup_sched_groups() would move the | ||
| 2271 | + Also, if we did, chain_to_prev_insn would move the | ||
| 2272 | deps of the debug insn to the call insn, modifying | ||
| 2273 | non-debug post-dependency counts of the debug insn | ||
| 2274 | dependencies and otherwise messing with the scheduling | ||
| 2275 | @@ -3222,6 +3223,37 @@ | ||
| 2276 | return true; | ||
| 2277 | } | ||
| 2278 | |||
| 2279 | +/* Return true if INSN should be made dependent on the previous instruction | ||
| 2280 | + group, and if all INSN's dependencies should be moved to the first | ||
| 2281 | + instruction of that group. */ | ||
| 2282 | + | ||
| 2283 | +static bool | ||
| 2284 | +chain_to_prev_insn_p (rtx insn) | ||
| 2285 | +{ | ||
| 2286 | + rtx prev, x; | ||
| 2287 | + | ||
| 2288 | + /* INSN forms a group with the previous instruction. */ | ||
| 2289 | + if (SCHED_GROUP_P (insn)) | ||
| 2290 | + return true; | ||
| 2291 | + | ||
| 2292 | + /* If the previous instruction clobbers a register R and this one sets | ||
| 2293 | + part of R, the clobber was added specifically to help us track the | ||
| 2294 | + liveness of R. There's no point scheduling the clobber and leaving | ||
| 2295 | + INSN behind, especially if we move the clobber to another block. */ | ||
| 2296 | + prev = prev_nonnote_nondebug_insn (insn); | ||
| 2297 | + if (prev | ||
| 2298 | + && INSN_P (prev) | ||
| 2299 | + && BLOCK_FOR_INSN (prev) == BLOCK_FOR_INSN (insn) | ||
| 2300 | + && GET_CODE (PATTERN (prev)) == CLOBBER) | ||
| 2301 | + { | ||
| 2302 | + x = XEXP (PATTERN (prev), 0); | ||
| 2303 | + if (set_of (x, insn)) | ||
| 2304 | + return true; | ||
| 2305 | + } | ||
| 2306 | + | ||
| 2307 | + return false; | ||
| 2308 | +} | ||
| 2309 | + | ||
| 2310 | /* Analyze INSN with DEPS as a context. */ | ||
| 2311 | void | ||
| 2312 | deps_analyze_insn (struct deps_desc *deps, rtx insn) | ||
| 2313 | @@ -3358,8 +3390,9 @@ | ||
| 2314 | |||
| 2315 | /* Fixup the dependencies in the sched group. */ | ||
| 2316 | if ((NONJUMP_INSN_P (insn) || JUMP_P (insn)) | ||
| 2317 | - && SCHED_GROUP_P (insn) && !sel_sched_p ()) | ||
| 2318 | - fixup_sched_groups (insn); | ||
| 2319 | + && chain_to_prev_insn_p (insn) | ||
| 2320 | + && !sel_sched_p ()) | ||
| 2321 | + chain_to_prev_insn (insn); | ||
| 2322 | } | ||
| 2323 | |||
| 2324 | /* Initialize DEPS for the new block beginning with HEAD. */ | ||
| 2325 | |||
| 2326 | === modified file 'gcc/sched-int.h' | ||
| 2327 | --- old/gcc/sched-int.h 2011-02-02 04:31:35 +0000 | ||
| 2328 | +++ new/gcc/sched-int.h 2012-02-08 23:39:02 +0000 | ||
| 2329 | @@ -651,7 +651,7 @@ | ||
| 2330 | |||
| 2331 | /* Do register pressure sensitive insn scheduling if the flag is set | ||
| 2332 | up. */ | ||
| 2333 | -extern bool sched_pressure_p; | ||
| 2334 | +extern enum sched_pressure_algorithm sched_pressure; | ||
| 2335 | |||
| 2336 | /* Map regno -> its cover class. The map defined only when | ||
| 2337 | SCHED_PRESSURE_P is true. */ | ||
| 2338 | @@ -773,16 +773,16 @@ | ||
| 2339 | |||
| 2340 | short cost; | ||
| 2341 | |||
| 2342 | + /* '> 0' if priority is valid, | ||
| 2343 | + '== 0' if priority was not yet computed, | ||
| 2344 | + '< 0' if priority in invalid and should be recomputed. */ | ||
| 2345 | + signed char priority_status; | ||
| 2346 | + | ||
| 2347 | /* Set if there's DEF-USE dependence between some speculatively | ||
| 2348 | moved load insn and this one. */ | ||
| 2349 | unsigned int fed_by_spec_load : 1; | ||
| 2350 | unsigned int is_load_insn : 1; | ||
| 2351 | |||
| 2352 | - /* '> 0' if priority is valid, | ||
| 2353 | - '== 0' if priority was not yet computed, | ||
| 2354 | - '< 0' if priority in invalid and should be recomputed. */ | ||
| 2355 | - signed char priority_status; | ||
| 2356 | - | ||
| 2357 | /* What speculations are necessary to apply to schedule the instruction. */ | ||
| 2358 | ds_t todo_spec; | ||
| 2359 | |||
| 2360 | @@ -817,6 +817,7 @@ | ||
| 2361 | /* Info about how scheduling the insn changes cost of register | ||
| 2362 | pressure excess (between source and target). */ | ||
| 2363 | int reg_pressure_excess_cost_change; | ||
| 2364 | + int model_index; | ||
| 2365 | }; | ||
| 2366 | |||
| 2367 | typedef struct _haifa_insn_data haifa_insn_data_def; | ||
| 2368 | @@ -839,6 +840,7 @@ | ||
| 2369 | #define INSN_REG_PRESSURE_EXCESS_COST_CHANGE(INSN) \ | ||
| 2370 | (HID (INSN)->reg_pressure_excess_cost_change) | ||
| 2371 | #define INSN_PRIORITY_STATUS(INSN) (HID (INSN)->priority_status) | ||
| 2372 | +#define INSN_MODEL_INDEX(INSN) (HID (INSN)->model_index) | ||
| 2373 | |||
| 2374 | typedef struct _haifa_deps_insn_data haifa_deps_insn_data_def; | ||
| 2375 | typedef haifa_deps_insn_data_def *haifa_deps_insn_data_t; | ||
| 2376 | |||
| 2377 | === modified file 'gcc/sched-rgn.c' | ||
| 2378 | --- old/gcc/sched-rgn.c 2011-06-04 10:15:48 +0000 | ||
| 2379 | +++ new/gcc/sched-rgn.c 2012-02-08 23:38:13 +0000 | ||
| 2380 | @@ -2943,7 +2943,7 @@ | ||
| 2381 | |||
| 2382 | sched_extend_ready_list (rgn_n_insns); | ||
| 2383 | |||
| 2384 | - if (sched_pressure_p) | ||
| 2385 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
| 2386 | { | ||
| 2387 | sched_init_region_reg_pressure_info (); | ||
| 2388 | for (bb = 0; bb < current_nr_blocks; bb++) | ||
| 2389 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106870.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106870.patch new file mode 100644 index 0000000000..1a5448403e --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106870.patch | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | 2012-02-20 Andrew Stubbs <ams@codesourcery.com> | ||
| 2 | |||
| 3 | gcc/ | ||
| 4 | * config/arm/arm.c (arm_print_operand): Avoid null-pointer | ||
| 5 | dereference from MEM_SIZE. | ||
| 6 | |||
| 7 | === modified file 'gcc/config/arm/arm.c' | ||
| 8 | --- old/gcc/config/arm/arm.c 2012-02-09 00:47:59 +0000 | ||
| 9 | +++ new/gcc/config/arm/arm.c 2012-02-20 15:32:26 +0000 | ||
| 10 | @@ -17446,6 +17446,7 @@ | ||
| 11 | rtx addr; | ||
| 12 | bool postinc = FALSE; | ||
| 13 | unsigned align, memsize, align_bits; | ||
| 14 | + rtx memsize_rtx; | ||
| 15 | |||
| 16 | gcc_assert (GET_CODE (x) == MEM); | ||
| 17 | addr = XEXP (x, 0); | ||
| 18 | @@ -17460,7 +17461,8 @@ | ||
| 19 | instruction (for some alignments) as an aid to the memory subsystem | ||
| 20 | of the target. */ | ||
| 21 | align = MEM_ALIGN (x) >> 3; | ||
| 22 | - memsize = INTVAL (MEM_SIZE (x)); | ||
| 23 | + memsize_rtx = MEM_SIZE (x); | ||
| 24 | + memsize = memsize_rtx ? INTVAL (memsize_rtx) : 0; | ||
| 25 | |||
| 26 | /* Only certain alignment specifiers are supported by the hardware. */ | ||
| 27 | if (memsize == 16 && (align % 32) == 0) | ||
| 28 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106872.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106872.patch new file mode 100644 index 0000000000..9bfd969df6 --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106872.patch | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | 2012-02-24 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline. | ||
| 4 | 2011-12-05 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 5 | |||
| 6 | gcc/ | ||
| 7 | * config/arm/arm.c (vfp3_const_double_for_fract_bits): Define. | ||
| 8 | * config/arm/arm-protos.h (vfp3_const_double_for_fract_bits): Declare. | ||
| 9 | * config/arm/constraints.md ("Dt"): New constraint. | ||
| 10 | * config/arm/predicates.md (const_double_vcvt_power_of_two_reciprocal): | ||
| 11 | New. | ||
| 12 | * config/arm/vfp.md (*arm_combine_vcvt_f32_s32): New. | ||
| 13 | (*arm_combine_vcvt_f32_u32): New. | ||
| 14 | |||
| 15 | LP:#900426 | ||
| 16 | |||
| 17 | 2011-12-06 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 18 | * config/arm/vfp.md (*combine_vcvt_f64_<FCVTI32typename>): Fix | ||
| 19 | formatting character for vmov.f64 case. | ||
| 20 | |||
| 21 | 2012-02-24 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 22 | |||
| 23 | gcc/ | ||
| 24 | * config/arm/arm.c (arm_print_operand): Remove wrongly merged code. | ||
| 25 | (vfp3_const_double_for_fract_bits): Likewise. | ||
| 26 | |||
| 27 | === modified file 'gcc/config/arm/arm-protos.h' | ||
| 28 | --- old/gcc/config/arm/arm-protos.h 2011-12-06 10:42:29 +0000 | ||
| 29 | +++ new/gcc/config/arm/arm-protos.h 2012-02-22 13:31:54 +0000 | ||
| 30 | @@ -238,6 +238,7 @@ | ||
| 31 | }; | ||
| 32 | |||
| 33 | extern const struct tune_params *current_tune; | ||
| 34 | +extern int vfp3_const_double_for_fract_bits (rtx); | ||
| 35 | #endif /* RTX_CODE */ | ||
| 36 | |||
| 37 | #endif /* ! GCC_ARM_PROTOS_H */ | ||
| 38 | |||
| 39 | === modified file 'gcc/config/arm/constraints.md' | ||
| 40 | --- old/gcc/config/arm/constraints.md 2011-12-06 10:42:29 +0000 | ||
| 41 | +++ new/gcc/config/arm/constraints.md 2012-02-22 13:31:54 +0000 | ||
| 42 | @@ -29,7 +29,7 @@ | ||
| 43 | ;; in Thumb-1 state: I, J, K, L, M, N, O | ||
| 44 | |||
| 45 | ;; The following multi-letter normal constraints have been used: | ||
| 46 | -;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dz | ||
| 47 | +;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz | ||
| 48 | ;; in Thumb-1 state: Pa, Pb, Pc, Pd | ||
| 49 | ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py | ||
| 50 | |||
| 51 | @@ -291,6 +291,12 @@ | ||
| 52 | (and (match_code "const_double") | ||
| 53 | (match_test "TARGET_32BIT && TARGET_VFP_DOUBLE && vfp3_const_double_rtx (op)"))) | ||
| 54 | |||
| 55 | +(define_constraint "Dt" | ||
| 56 | + "@internal | ||
| 57 | + In ARM/ Thumb2 a const_double which can be used with a vcvt.f32.s32 with fract bits operation" | ||
| 58 | + (and (match_code "const_double") | ||
| 59 | + (match_test "TARGET_32BIT && TARGET_VFP && vfp3_const_double_for_fract_bits (op)"))) | ||
| 60 | + | ||
| 61 | (define_memory_constraint "Ut" | ||
| 62 | "@internal | ||
| 63 | In ARM/Thumb-2 state an address valid for loading/storing opaque structure | ||
| 64 | |||
| 65 | === modified file 'gcc/config/arm/predicates.md' | ||
| 66 | --- old/gcc/config/arm/predicates.md 2011-12-06 10:42:29 +0000 | ||
| 67 | +++ new/gcc/config/arm/predicates.md 2012-02-22 13:31:54 +0000 | ||
| 68 | @@ -725,6 +725,11 @@ | ||
| 69 | return true; | ||
| 70 | }) | ||
| 71 | |||
| 72 | +(define_predicate "const_double_vcvt_power_of_two_reciprocal" | ||
| 73 | + (and (match_code "const_double") | ||
| 74 | + (match_test "TARGET_32BIT && TARGET_VFP | ||
| 75 | + && vfp3_const_double_for_fract_bits (op)"))) | ||
| 76 | + | ||
| 77 | (define_special_predicate "neon_struct_operand" | ||
| 78 | (and (match_code "mem") | ||
| 79 | (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 2)"))) | ||
| 80 | |||
| 81 | === modified file 'gcc/config/arm/vfp.md' | ||
| 82 | --- old/gcc/config/arm/vfp.md 2011-12-06 10:42:29 +0000 | ||
| 83 | +++ new/gcc/config/arm/vfp.md 2012-02-22 13:31:54 +0000 | ||
| 84 | @@ -1131,9 +1131,40 @@ | ||
| 85 | (set_attr "type" "fcmpd")] | ||
| 86 | ) | ||
| 87 | |||
| 88 | +;; Fixed point to floating point conversions. | ||
| 89 | +(define_code_iterator FCVT [unsigned_float float]) | ||
| 90 | +(define_code_attr FCVTI32typename [(unsigned_float "u32") (float "s32")]) | ||
| 91 | + | ||
| 92 | +(define_insn "*combine_vcvt_f32_<FCVTI32typename>" | ||
| 93 | + [(set (match_operand:SF 0 "s_register_operand" "=t") | ||
| 94 | + (mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0")) | ||
| 95 | + (match_operand 2 | ||
| 96 | + "const_double_vcvt_power_of_two_reciprocal" "Dt")))] | ||
| 97 | + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math" | ||
| 98 | + "vcvt.f32.<FCVTI32typename>\\t%0, %1, %v2" | ||
| 99 | + [(set_attr "predicable" "no") | ||
| 100 | + (set_attr "type" "f_cvt")] | ||
| 101 | +) | ||
| 102 | + | ||
| 103 | +;; Not the ideal way of implementing this. Ideally we would be able to split | ||
| 104 | +;; this into a move to a DP register and then a vcvt.f64.i32 | ||
| 105 | +(define_insn "*combine_vcvt_f64_<FCVTI32typename>" | ||
| 106 | + [(set (match_operand:DF 0 "s_register_operand" "=x,x,w") | ||
| 107 | + (mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r")) | ||
| 108 | + (match_operand 2 | ||
| 109 | + "const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))] | ||
| 110 | + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math | ||
| 111 | + && !TARGET_VFP_SINGLE" | ||
| 112 | + "@ | ||
| 113 | + vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2 | ||
| 114 | + vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2 | ||
| 115 | + vmov.f64\\t%P0, %1, %1\; vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2" | ||
| 116 | + [(set_attr "predicable" "no") | ||
| 117 | + (set_attr "type" "f_cvt") | ||
| 118 | + (set_attr "length" "8")] | ||
| 119 | +) | ||
| 120 | |||
| 121 | ;; Store multiple insn used in function prologue. | ||
| 122 | - | ||
| 123 | (define_insn "*push_multi_vfp" | ||
| 124 | [(match_parallel 2 "multi_register_push" | ||
| 125 | [(set (match_operand:BLK 0 "memory_operand" "=m") | ||
| 126 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106873.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106873.patch new file mode 100644 index 0000000000..5ce71a5138 --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106873.patch | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | 2012-02-24 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 2 | |||
| 3 | LP:#922474 | ||
| 4 | gcc/ | ||
| 5 | * config/arm/sync.md (sync_lock_releasedi): Define. | ||
| 6 | (arm_sync_lock_releasedi): Likewise. | ||
| 7 | gcc/testsuite | ||
| 8 | Backport from mainline. | ||
| 9 | 2012-01-30 Greta Yorsh <Greta.Yorsh@arm.com> | ||
| 10 | * gcc.target/arm/di-longlong64-sync-withldrexd.c: Accept | ||
| 11 | new code generated for __sync_lock_release. | ||
| 12 | |||
| 13 | === modified file 'gcc/config/arm/arm.md' | ||
| 14 | --- old/gcc/config/arm/arm.md 2012-02-01 14:13:07 +0000 | ||
| 15 | +++ new/gcc/config/arm/arm.md 2012-02-22 18:37:56 +0000 | ||
| 16 | @@ -157,6 +157,7 @@ | ||
| 17 | (VUNSPEC_SYNC_OP 23) ; Represent a sync_<op> | ||
| 18 | (VUNSPEC_SYNC_NEW_OP 24) ; Represent a sync_new_<op> | ||
| 19 | (VUNSPEC_SYNC_OLD_OP 25) ; Represent a sync_old_<op> | ||
| 20 | + (VUNSPEC_SYNC_RELEASE 26) ; Represent a sync_lock_release. | ||
| 21 | ] | ||
| 22 | ) | ||
| 23 | |||
| 24 | |||
| 25 | === modified file 'gcc/config/arm/sync.md' | ||
| 26 | --- old/gcc/config/arm/sync.md 2011-10-14 15:47:15 +0000 | ||
| 27 | +++ new/gcc/config/arm/sync.md 2012-02-22 18:37:56 +0000 | ||
| 28 | @@ -494,3 +494,36 @@ | ||
| 29 | (set_attr "conds" "unconditional") | ||
| 30 | (set_attr "predicable" "no")]) | ||
| 31 | |||
| 32 | +(define_expand "sync_lock_releasedi" | ||
| 33 | + [(match_operand:DI 0 "memory_operand") | ||
| 34 | + (match_operand:DI 1 "s_register_operand")] | ||
| 35 | + "TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN && TARGET_HAVE_MEMORY_BARRIER" | ||
| 36 | + { | ||
| 37 | + struct arm_sync_generator generator; | ||
| 38 | + rtx tmp1 = gen_reg_rtx (DImode); | ||
| 39 | + generator.op = arm_sync_generator_omn; | ||
| 40 | + generator.u.omn = gen_arm_sync_lock_releasedi; | ||
| 41 | + arm_expand_sync (DImode, &generator, operands[1], operands[0], NULL, tmp1); | ||
| 42 | + DONE; | ||
| 43 | + } | ||
| 44 | +) | ||
| 45 | + | ||
| 46 | +(define_insn "arm_sync_lock_releasedi" | ||
| 47 | + [(set (match_operand:DI 2 "s_register_operand" "=&r") | ||
| 48 | + (unspec_volatile:DI [(match_operand:DI 1 "arm_sync_memory_operand" "+Q") | ||
| 49 | + (match_operand:DI 0 "s_register_operand" "r")] | ||
| 50 | + VUNSPEC_SYNC_RELEASE)) | ||
| 51 | + (clobber (reg:CC CC_REGNUM)) | ||
| 52 | + (clobber (match_scratch:SI 3 "=&r"))] | ||
| 53 | + "TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN && TARGET_HAVE_MEMORY_BARRIER" | ||
| 54 | + { | ||
| 55 | + return arm_output_sync_insn (insn, operands); | ||
| 56 | + } | ||
| 57 | + [(set_attr "sync_memory" "1") | ||
| 58 | + (set_attr "sync_result" "2") | ||
| 59 | + (set_attr "sync_t1" "2") | ||
| 60 | + (set_attr "sync_t2" "3") | ||
| 61 | + (set_attr "sync_new_value" "0") | ||
| 62 | + (set_attr "conds" "clob") | ||
| 63 | + (set_attr "predicable" "no")] | ||
| 64 | +) | ||
| 65 | |||
| 66 | === modified file 'gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c' | ||
| 67 | --- old/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c 2011-10-14 15:56:32 +0000 | ||
| 68 | +++ new/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c 2012-02-22 18:37:56 +0000 | ||
| 69 | @@ -10,8 +10,8 @@ | ||
| 70 | #include "../../gcc.dg/di-longlong64-sync-1.c" | ||
| 71 | |||
| 72 | /* We should be using ldrexd, strexd and no helpers or shorter ldrex. */ | ||
| 73 | -/* { dg-final { scan-assembler-times "\tldrexd" 46 } } */ | ||
| 74 | -/* { dg-final { scan-assembler-times "\tstrexd" 46 } } */ | ||
| 75 | +/* { dg-final { scan-assembler-times "\tldrexd" 48 } } */ | ||
| 76 | +/* { dg-final { scan-assembler-times "\tstrexd" 48 } } */ | ||
| 77 | /* { dg-final { scan-assembler-not "__sync_" } } */ | ||
| 78 | /* { dg-final { scan-assembler-not "ldrex\t" } } */ | ||
| 79 | /* { dg-final { scan-assembler-not "strex\t" } } */ | ||
| 80 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106874.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106874.patch new file mode 100644 index 0000000000..092650dc9d --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106874.patch | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | 2012-02-24 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org> | ||
| 2 | |||
| 3 | Backport from mainline. | ||
| 4 | gcc/ | ||
| 5 | 2012-02-21 Matthew Gretton-Dann <matthew.gretton-dann@arm.com> | ||
| 6 | |||
| 7 | Revert r183011 | ||
| 8 | * config/arm/arm-cores.def (cortex-a15): Use generic Cortex tuning | ||
| 9 | parameters. | ||
| 10 | * config/arm/arm.c (arm_cortex_a15_tune): Remove. | ||
| 11 | |||
| 12 | === modified file 'gcc/config/arm/arm-cores.def' | ||
| 13 | --- old/gcc/config/arm/arm-cores.def 2012-01-23 00:36:02 +0000 | ||
| 14 | +++ new/gcc/config/arm/arm-cores.def 2012-02-22 15:53:56 +0000 | ||
| 15 | @@ -129,7 +129,7 @@ | ||
| 16 | ARM_CORE("cortex-a7", cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex) | ||
| 17 | ARM_CORE("cortex-a8", cortexa8, 7A, FL_LDSCHED, cortex) | ||
| 18 | ARM_CORE("cortex-a9", cortexa9, 7A, FL_LDSCHED, cortex_a9) | ||
| 19 | -ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) | ||
| 20 | +ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex) | ||
| 21 | ARM_CORE("cortex-r4", cortexr4, 7R, FL_LDSCHED, cortex) | ||
| 22 | ARM_CORE("cortex-r4f", cortexr4f, 7R, FL_LDSCHED, cortex) | ||
| 23 | ARM_CORE("cortex-r5", cortexr5, 7R, FL_LDSCHED | FL_ARM_DIV, cortex) | ||
| 24 | |||
| 25 | === modified file 'gcc/config/arm/arm.c' | ||
| 26 | --- old/gcc/config/arm/arm.c 2012-02-24 16:20:29 +0000 | ||
| 27 | +++ new/gcc/config/arm/arm.c 2012-02-24 17:33:58 +0000 | ||
| 28 | @@ -988,17 +988,6 @@ | ||
| 29 | arm_default_branch_cost | ||
| 30 | }; | ||
| 31 | |||
| 32 | -const struct tune_params arm_cortex_a15_tune = | ||
| 33 | -{ | ||
| 34 | - arm_9e_rtx_costs, | ||
| 35 | - NULL, | ||
| 36 | - 1, /* Constant limit. */ | ||
| 37 | - 1, /* Max cond insns. */ | ||
| 38 | - ARM_PREFETCH_NOT_BENEFICIAL, /* TODO: Calculate correct values. */ | ||
| 39 | - false, /* Prefer constant pool. */ | ||
| 40 | - arm_cortex_a5_branch_cost | ||
| 41 | -}; | ||
| 42 | - | ||
| 43 | const struct tune_params arm_fa726te_tune = | ||
| 44 | { | ||
| 45 | arm_9e_rtx_costs, | ||
| 46 | |||
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4_6-branch-linaro-backports.inc b/meta-oe/recipes-devtools/gcc/gcc-4_6-branch-linaro-backports.inc index e42aeeaadf..90a857d9af 100644 --- a/meta-oe/recipes-devtools/gcc/gcc-4_6-branch-linaro-backports.inc +++ b/meta-oe/recipes-devtools/gcc/gcc-4_6-branch-linaro-backports.inc | |||
| @@ -4,7 +4,6 @@ file://linaro/gcc-4.6-linaro-r106733.patch \ | |||
| 4 | file://linaro/gcc-4.6-linaro-r106737.patch \ | 4 | file://linaro/gcc-4.6-linaro-r106737.patch \ |
| 5 | file://linaro/gcc-4.6-linaro-r106738.patch \ | 5 | file://linaro/gcc-4.6-linaro-r106738.patch \ |
| 6 | file://linaro/gcc-4.6-linaro-r106739.patch \ | 6 | file://linaro/gcc-4.6-linaro-r106739.patch \ |
| 7 | file://linaro/gcc-4.6-linaro-r106740.patch \ | ||
| 8 | file://linaro/gcc-4.6-linaro-r106741.patch \ | 7 | file://linaro/gcc-4.6-linaro-r106741.patch \ |
| 9 | file://linaro/gcc-4.6-linaro-r106742.patch \ | 8 | file://linaro/gcc-4.6-linaro-r106742.patch \ |
| 10 | file://linaro/gcc-4.6-linaro-r106744.patch \ | 9 | file://linaro/gcc-4.6-linaro-r106744.patch \ |
| @@ -81,6 +80,17 @@ file://linaro/gcc-4.6-linaro-r106845.patch \ | |||
| 81 | file://linaro/gcc-4.6-linaro-r106846.patch \ | 80 | file://linaro/gcc-4.6-linaro-r106846.patch \ |
| 82 | file://linaro/gcc-4.6-linaro-r106848.patch \ | 81 | file://linaro/gcc-4.6-linaro-r106848.patch \ |
| 83 | file://linaro/gcc-4.6-linaro-r106853.patch \ | 82 | file://linaro/gcc-4.6-linaro-r106853.patch \ |
| 84 | file://linaro/gcc-4.6-linaro-r106854.patch \ | ||
| 85 | file://linaro/gcc-4.6-linaro-r106855.patch \ | 83 | file://linaro/gcc-4.6-linaro-r106855.patch \ |
| 84 | file://linaro/gcc-4.6-linaro-r106860.patch \ | ||
| 85 | file://linaro/gcc-4.6-linaro-r106861.patch \ | ||
| 86 | file://linaro/gcc-4.6-linaro-r106862.patch \ | ||
| 87 | file://linaro/gcc-4.6-linaro-r106863.patch \ | ||
| 88 | file://linaro/gcc-4.6-linaro-r106864.patch \ | ||
| 89 | file://linaro/gcc-4.6-linaro-r106865.patch \ | ||
| 90 | file://linaro/gcc-4.6-linaro-r106869.patch \ | ||
| 91 | file://linaro/gcc-4.6-linaro-r106870.patch \ | ||
| 92 | file://linaro/gcc-4.6-linaro-r106872.patch \ | ||
| 93 | file://linaro/gcc-4.6-linaro-r106873.patch \ | ||
| 94 | file://linaro/gcc-4.6-linaro-r106874.patch \ | ||
| 95 | file://linaro/fix_linaro_106872.patch \ | ||
| 86 | " | 96 | " |
