Mercurial > hg > CbC > CbC_gcc
comparison gcc/dse.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* RTL dead store elimination. | 1 /* RTL dead store elimination. |
2 Copyright (C) 2005-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2005-2018 Free Software Foundation, Inc. |
3 | 3 |
4 Contributed by Richard Sandiford <rsandifor@codesourcery.com> | 4 Contributed by Richard Sandiford <rsandifor@codesourcery.com> |
5 and Kenneth Zadeck <zadeck@naturalbridge.com> | 5 and Kenneth Zadeck <zadeck@naturalbridge.com> |
6 | 6 |
7 This file is part of GCC. | 7 This file is part of GCC. |
241 rtx mem; | 241 rtx mem; |
242 | 242 |
243 /* Canonized MEM address for use by canon_true_dependence. */ | 243 /* Canonized MEM address for use by canon_true_dependence. */ |
244 rtx mem_addr; | 244 rtx mem_addr; |
245 | 245 |
246 /* The offset of the first and byte before the last byte associated | 246 /* The offset of the first byte associated with the operation. */ |
247 with the operation. */ | 247 poly_int64 offset; |
248 HOST_WIDE_INT begin, end; | 248 |
249 /* The number of bytes covered by the operation. This is always exact | |
250 and known (rather than -1). */ | |
251 poly_int64 width; | |
249 | 252 |
250 union | 253 union |
251 { | 254 { |
252 /* A bitmask as wide as the number of bytes in the word that | 255 /* A bitmask as wide as the number of bytes in the word that |
253 contains a 1 if the byte may be needed. The store is unused if | 256 contains a 1 if the byte may be needed. The store is unused if |
254 all of the bits are 0. This is used if IS_LARGE is false. */ | 257 all of the bits are 0. This is used if IS_LARGE is false. */ |
255 unsigned HOST_WIDE_INT small_bitmask; | 258 unsigned HOST_WIDE_INT small_bitmask; |
256 | 259 |
257 struct | 260 struct |
258 { | 261 { |
259 /* A bitmap with one bit per byte. Cleared bit means the position | 262 /* A bitmap with one bit per byte, or null if the number of |
260 is needed. Used if IS_LARGE is false. */ | 263 bytes isn't known at compile time. A cleared bit means |
264 the position is needed. Used if IS_LARGE is true. */ | |
261 bitmap bmap; | 265 bitmap bmap; |
262 | 266 |
263 /* Number of set bits (i.e. unneeded bytes) in BITMAP. If it is | 267 /* When BITMAP is nonnull, this counts the number of set bits |
264 equal to END - BEGIN, the whole store is unused. */ | 268 (i.e. unneeded bytes) in the bitmap. If it is equal to |
269 WIDTH, the whole store is unused. | |
270 | |
271 When BITMAP is null: | |
272 - the store is definitely not needed when COUNT == 1 | |
273 - all the store is needed when COUNT == 0 and RHS is nonnull | |
274 - otherwise we don't know which parts of the store are needed. */ | |
265 int count; | 275 int count; |
266 } large; | 276 } large; |
267 } positions_needed; | 277 } positions_needed; |
268 | 278 |
269 /* The next store info for this insn. */ | 279 /* The next store info for this insn. */ |
302 struct read_info_type | 312 struct read_info_type |
303 { | 313 { |
304 /* The id of the mem group of the base address. */ | 314 /* The id of the mem group of the base address. */ |
305 int group_id; | 315 int group_id; |
306 | 316 |
307 /* The offset of the first and byte after the last byte associated | 317 /* The offset of the first byte associated with the operation. */ |
308 with the operation. If begin == end == 0, the read did not have | 318 poly_int64 offset; |
309 a constant offset. */ | 319 |
310 int begin, end; | 320 /* The number of bytes covered by the operation, or -1 if not known. */ |
321 poly_int64 width; | |
311 | 322 |
312 /* The mem being read. */ | 323 /* The mem being read. */ |
313 rtx mem; | 324 rtx mem; |
314 | 325 |
315 /* The next read_info for this insn. */ | 326 /* The next read_info for this insn. */ |
584 /* Locations that are killed by calls in the global phase. */ | 595 /* Locations that are killed by calls in the global phase. */ |
585 static bitmap kill_on_calls; | 596 static bitmap kill_on_calls; |
586 | 597 |
587 /* The number of bits used in the global bitmaps. */ | 598 /* The number of bits used in the global bitmaps. */ |
588 static unsigned int current_position; | 599 static unsigned int current_position; |
600 | |
601 /* Print offset range [OFFSET, OFFSET + WIDTH) to FILE. */ | |
602 | |
603 static void | |
604 print_range (FILE *file, poly_int64 offset, poly_int64 width) | |
605 { | |
606 fprintf (file, "["); | |
607 print_dec (offset, file, SIGNED); | |
608 fprintf (file, ".."); | |
609 print_dec (offset + width, file, SIGNED); | |
610 fprintf (file, ")"); | |
611 } | |
589 | 612 |
590 /*---------------------------------------------------------------------------- | 613 /*---------------------------------------------------------------------------- |
591 Zeroth step. | 614 Zeroth step. |
592 | 615 |
593 Initialization. | 616 Initialization. |
922 | 945 |
923 /* Set the store* bitmaps offset_map_size* fields in GROUP based on | 946 /* Set the store* bitmaps offset_map_size* fields in GROUP based on |
924 OFFSET and WIDTH. */ | 947 OFFSET and WIDTH. */ |
925 | 948 |
926 static void | 949 static void |
927 set_usage_bits (group_info *group, HOST_WIDE_INT offset, HOST_WIDE_INT width, | 950 set_usage_bits (group_info *group, poly_int64 offset, poly_int64 width, |
928 tree expr) | 951 tree expr) |
929 { | 952 { |
930 HOST_WIDE_INT i; | 953 /* Non-constant offsets and widths act as global kills, so there's no point |
954 trying to use them to derive global DSE candidates. */ | |
955 HOST_WIDE_INT i, const_offset, const_width; | |
931 bool expr_escapes = can_escape (expr); | 956 bool expr_escapes = can_escape (expr); |
932 if (offset > -MAX_OFFSET && offset + width < MAX_OFFSET) | 957 if (offset.is_constant (&const_offset) |
933 for (i=offset; i<offset+width; i++) | 958 && width.is_constant (&const_width) |
959 && const_offset > -MAX_OFFSET | |
960 && const_offset + const_width < MAX_OFFSET) | |
961 for (i = const_offset; i < const_offset + const_width; ++i) | |
934 { | 962 { |
935 bitmap store1; | 963 bitmap store1; |
936 bitmap store2; | 964 bitmap store2; |
937 bitmap escaped; | 965 bitmap escaped; |
938 int ai; | 966 int ai; |
1062 FOR_READ is true if this is a mem read and false if not. */ | 1090 FOR_READ is true if this is a mem read and false if not. */ |
1063 | 1091 |
1064 static bool | 1092 static bool |
1065 canon_address (rtx mem, | 1093 canon_address (rtx mem, |
1066 int *group_id, | 1094 int *group_id, |
1067 HOST_WIDE_INT *offset, | 1095 poly_int64 *offset, |
1068 cselib_val **base) | 1096 cselib_val **base) |
1069 { | 1097 { |
1070 machine_mode address_mode = get_address_mode (mem); | 1098 machine_mode address_mode = get_address_mode (mem); |
1071 rtx mem_address = XEXP (mem, 0); | 1099 rtx mem_address = XEXP (mem, 0); |
1072 rtx expanded_address, address; | 1100 rtx expanded_address, address; |
1129 } | 1157 } |
1130 | 1158 |
1131 if (GET_CODE (address) == CONST) | 1159 if (GET_CODE (address) == CONST) |
1132 address = XEXP (address, 0); | 1160 address = XEXP (address, 0); |
1133 | 1161 |
1134 if (GET_CODE (address) == PLUS | 1162 address = strip_offset_and_add (address, offset); |
1135 && CONST_INT_P (XEXP (address, 1))) | |
1136 { | |
1137 *offset = INTVAL (XEXP (address, 1)); | |
1138 address = XEXP (address, 0); | |
1139 } | |
1140 | 1163 |
1141 if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem)) | 1164 if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem)) |
1142 && const_or_frame_p (address)) | 1165 && const_or_frame_p (address)) |
1143 { | 1166 { |
1144 group_info *group = get_group_info (address); | 1167 group_info *group = get_group_info (address); |
1145 | 1168 |
1146 if (dump_file && (dump_flags & TDF_DETAILS)) | 1169 if (dump_file && (dump_flags & TDF_DETAILS)) |
1147 fprintf (dump_file, " gid=%d offset=%d \n", | 1170 { |
1148 group->id, (int)*offset); | 1171 fprintf (dump_file, " gid=%d offset=", group->id); |
1172 print_dec (*offset, dump_file); | |
1173 fprintf (dump_file, "\n"); | |
1174 } | |
1149 *base = NULL; | 1175 *base = NULL; |
1150 *group_id = group->id; | 1176 *group_id = group->id; |
1151 return true; | 1177 return true; |
1152 } | 1178 } |
1153 } | 1179 } |
1160 if (dump_file && (dump_flags & TDF_DETAILS)) | 1186 if (dump_file && (dump_flags & TDF_DETAILS)) |
1161 fprintf (dump_file, " no cselib val - should be a wild read.\n"); | 1187 fprintf (dump_file, " no cselib val - should be a wild read.\n"); |
1162 return false; | 1188 return false; |
1163 } | 1189 } |
1164 if (dump_file && (dump_flags & TDF_DETAILS)) | 1190 if (dump_file && (dump_flags & TDF_DETAILS)) |
1165 fprintf (dump_file, " varying cselib base=%u:%u offset = %d\n", | 1191 { |
1166 (*base)->uid, (*base)->hash, (int)*offset); | 1192 fprintf (dump_file, " varying cselib base=%u:%u offset = ", |
1193 (*base)->uid, (*base)->hash); | |
1194 print_dec (*offset, dump_file); | |
1195 fprintf (dump_file, "\n"); | |
1196 } | |
1167 return true; | 1197 return true; |
1168 } | 1198 } |
1169 | 1199 |
1170 | 1200 |
1171 /* Clear the rhs field from the active_local_stores array. */ | 1201 /* Clear the rhs field from the active_local_stores array. */ |
1210 static inline void | 1240 static inline void |
1211 set_all_positions_unneeded (store_info *s_info) | 1241 set_all_positions_unneeded (store_info *s_info) |
1212 { | 1242 { |
1213 if (__builtin_expect (s_info->is_large, false)) | 1243 if (__builtin_expect (s_info->is_large, false)) |
1214 { | 1244 { |
1215 int pos, end = s_info->end - s_info->begin; | 1245 HOST_WIDE_INT width; |
1216 for (pos = 0; pos < end; pos++) | 1246 if (s_info->width.is_constant (&width)) |
1217 bitmap_set_bit (s_info->positions_needed.large.bmap, pos); | 1247 { |
1218 s_info->positions_needed.large.count = end; | 1248 bitmap_set_range (s_info->positions_needed.large.bmap, 0, width); |
1249 s_info->positions_needed.large.count = width; | |
1250 } | |
1251 else | |
1252 { | |
1253 gcc_checking_assert (!s_info->positions_needed.large.bmap); | |
1254 s_info->positions_needed.large.count = 1; | |
1255 } | |
1219 } | 1256 } |
1220 else | 1257 else |
1221 s_info->positions_needed.small_bitmask = HOST_WIDE_INT_0U; | 1258 s_info->positions_needed.small_bitmask = HOST_WIDE_INT_0U; |
1222 } | 1259 } |
1223 | 1260 |
1225 | 1262 |
1226 static inline bool | 1263 static inline bool |
1227 any_positions_needed_p (store_info *s_info) | 1264 any_positions_needed_p (store_info *s_info) |
1228 { | 1265 { |
1229 if (__builtin_expect (s_info->is_large, false)) | 1266 if (__builtin_expect (s_info->is_large, false)) |
1230 return (s_info->positions_needed.large.count | 1267 { |
1231 < s_info->end - s_info->begin); | 1268 HOST_WIDE_INT width; |
1269 if (s_info->width.is_constant (&width)) | |
1270 { | |
1271 gcc_checking_assert (s_info->positions_needed.large.bmap); | |
1272 return s_info->positions_needed.large.count < width; | |
1273 } | |
1274 else | |
1275 { | |
1276 gcc_checking_assert (!s_info->positions_needed.large.bmap); | |
1277 return s_info->positions_needed.large.count == 0; | |
1278 } | |
1279 } | |
1232 else | 1280 else |
1233 return (s_info->positions_needed.small_bitmask != HOST_WIDE_INT_0U); | 1281 return (s_info->positions_needed.small_bitmask != HOST_WIDE_INT_0U); |
1234 } | 1282 } |
1235 | 1283 |
1236 /* Return TRUE if all bytes START through START+WIDTH-1 from S_INFO | 1284 /* Return TRUE if all bytes START through START+WIDTH-1 from S_INFO |
1237 store are needed. */ | 1285 store are known to be needed. */ |
1238 | 1286 |
1239 static inline bool | 1287 static inline bool |
1240 all_positions_needed_p (store_info *s_info, int start, int width) | 1288 all_positions_needed_p (store_info *s_info, poly_int64 start, |
1241 { | 1289 poly_int64 width) |
1290 { | |
1291 gcc_assert (s_info->rhs); | |
1292 if (!s_info->width.is_constant ()) | |
1293 { | |
1294 gcc_assert (s_info->is_large | |
1295 && !s_info->positions_needed.large.bmap); | |
1296 return s_info->positions_needed.large.count == 0; | |
1297 } | |
1298 | |
1299 /* Otherwise, if START and WIDTH are non-constant, we're asking about | |
1300 a non-constant region of a constant-sized store. We can't say for | |
1301 sure that all positions are needed. */ | |
1302 HOST_WIDE_INT const_start, const_width; | |
1303 if (!start.is_constant (&const_start) | |
1304 || !width.is_constant (&const_width)) | |
1305 return false; | |
1306 | |
1242 if (__builtin_expect (s_info->is_large, false)) | 1307 if (__builtin_expect (s_info->is_large, false)) |
1243 { | 1308 { |
1244 int end = start + width; | 1309 for (HOST_WIDE_INT i = const_start; i < const_start + const_width; ++i) |
1245 while (start < end) | 1310 if (bitmap_bit_p (s_info->positions_needed.large.bmap, i)) |
1246 if (bitmap_bit_p (s_info->positions_needed.large.bmap, start++)) | |
1247 return false; | 1311 return false; |
1248 return true; | 1312 return true; |
1249 } | 1313 } |
1250 else | 1314 else |
1251 { | 1315 { |
1252 unsigned HOST_WIDE_INT mask = lowpart_bitmask (width) << start; | 1316 unsigned HOST_WIDE_INT mask |
1317 = lowpart_bitmask (const_width) << const_start; | |
1253 return (s_info->positions_needed.small_bitmask & mask) == mask; | 1318 return (s_info->positions_needed.small_bitmask & mask) == mask; |
1254 } | 1319 } |
1255 } | 1320 } |
1256 | 1321 |
1257 | 1322 |
1258 static rtx get_stored_val (store_info *, machine_mode, HOST_WIDE_INT, | 1323 static rtx get_stored_val (store_info *, machine_mode, poly_int64, |
1259 HOST_WIDE_INT, basic_block, bool); | 1324 poly_int64, basic_block, bool); |
1260 | 1325 |
1261 | 1326 |
1262 /* BODY is an instruction pattern that belongs to INSN. Return 1 if | 1327 /* BODY is an instruction pattern that belongs to INSN. Return 1 if |
1263 there is a candidate store, after adding it to the appropriate | 1328 there is a candidate store, after adding it to the appropriate |
1264 local store group if so. */ | 1329 local store group if so. */ |
1265 | 1330 |
1266 static int | 1331 static int |
1267 record_store (rtx body, bb_info_t bb_info) | 1332 record_store (rtx body, bb_info_t bb_info) |
1268 { | 1333 { |
1269 rtx mem, rhs, const_rhs, mem_addr; | 1334 rtx mem, rhs, const_rhs, mem_addr; |
1270 HOST_WIDE_INT offset = 0; | 1335 poly_int64 offset = 0; |
1271 HOST_WIDE_INT width = 0; | 1336 poly_int64 width = 0; |
1272 insn_info_t insn_info = bb_info->last_insn; | 1337 insn_info_t insn_info = bb_info->last_insn; |
1273 store_info *store_info = NULL; | 1338 store_info *store_info = NULL; |
1274 int group_id; | 1339 int group_id; |
1275 cselib_val *base = NULL; | 1340 cselib_val *base = NULL; |
1276 insn_info_t ptr, last, redundant_reason; | 1341 insn_info_t ptr, last, redundant_reason; |
1298 } | 1363 } |
1299 | 1364 |
1300 /* At this point we know mem is a mem. */ | 1365 /* At this point we know mem is a mem. */ |
1301 if (GET_MODE (mem) == BLKmode) | 1366 if (GET_MODE (mem) == BLKmode) |
1302 { | 1367 { |
1368 HOST_WIDE_INT const_size; | |
1303 if (GET_CODE (XEXP (mem, 0)) == SCRATCH) | 1369 if (GET_CODE (XEXP (mem, 0)) == SCRATCH) |
1304 { | 1370 { |
1305 if (dump_file && (dump_flags & TDF_DETAILS)) | 1371 if (dump_file && (dump_flags & TDF_DETAILS)) |
1306 fprintf (dump_file, " adding wild read for (clobber (mem:BLK (scratch))\n"); | 1372 fprintf (dump_file, " adding wild read for (clobber (mem:BLK (scratch))\n"); |
1307 add_wild_read (bb_info); | 1373 add_wild_read (bb_info); |
1309 return 0; | 1375 return 0; |
1310 } | 1376 } |
1311 /* Handle (set (mem:BLK (addr) [... S36 ...]) (const_int 0)) | 1377 /* Handle (set (mem:BLK (addr) [... S36 ...]) (const_int 0)) |
1312 as memset (addr, 0, 36); */ | 1378 as memset (addr, 0, 36); */ |
1313 else if (!MEM_SIZE_KNOWN_P (mem) | 1379 else if (!MEM_SIZE_KNOWN_P (mem) |
1314 || MEM_SIZE (mem) <= 0 | 1380 || maybe_le (MEM_SIZE (mem), 0) |
1315 || MEM_SIZE (mem) > MAX_OFFSET | 1381 /* This is a limit on the bitmap size, which is only relevant |
1382 for constant-sized MEMs. */ | |
1383 || (MEM_SIZE (mem).is_constant (&const_size) | |
1384 && const_size > MAX_OFFSET) | |
1316 || GET_CODE (body) != SET | 1385 || GET_CODE (body) != SET |
1317 || !CONST_INT_P (SET_SRC (body))) | 1386 || !CONST_INT_P (SET_SRC (body))) |
1318 { | 1387 { |
1319 if (!store_is_unused) | 1388 if (!store_is_unused) |
1320 { | 1389 { |
1340 if (GET_MODE (mem) == BLKmode) | 1409 if (GET_MODE (mem) == BLKmode) |
1341 width = MEM_SIZE (mem); | 1410 width = MEM_SIZE (mem); |
1342 else | 1411 else |
1343 width = GET_MODE_SIZE (GET_MODE (mem)); | 1412 width = GET_MODE_SIZE (GET_MODE (mem)); |
1344 | 1413 |
1414 if (!endpoint_representable_p (offset, width)) | |
1415 { | |
1416 clear_rhs_from_active_local_stores (); | |
1417 return 0; | |
1418 } | |
1419 | |
1420 if (known_eq (width, 0)) | |
1421 return 0; | |
1422 | |
1345 if (group_id >= 0) | 1423 if (group_id >= 0) |
1346 { | 1424 { |
1347 /* In the restrictive case where the base is a constant or the | 1425 /* In the restrictive case where the base is a constant or the |
1348 frame pointer we can do global analysis. */ | 1426 frame pointer we can do global analysis. */ |
1349 | 1427 |
1353 | 1431 |
1354 store_info = rtx_store_info_pool.allocate (); | 1432 store_info = rtx_store_info_pool.allocate (); |
1355 set_usage_bits (group, offset, width, expr); | 1433 set_usage_bits (group, offset, width, expr); |
1356 | 1434 |
1357 if (dump_file && (dump_flags & TDF_DETAILS)) | 1435 if (dump_file && (dump_flags & TDF_DETAILS)) |
1358 fprintf (dump_file, " processing const base store gid=%d[%d..%d)\n", | 1436 { |
1359 group_id, (int)offset, (int)(offset+width)); | 1437 fprintf (dump_file, " processing const base store gid=%d", |
1438 group_id); | |
1439 print_range (dump_file, offset, width); | |
1440 fprintf (dump_file, "\n"); | |
1441 } | |
1360 } | 1442 } |
1361 else | 1443 else |
1362 { | 1444 { |
1363 if (may_be_sp_based_p (XEXP (mem, 0))) | 1445 if (may_be_sp_based_p (XEXP (mem, 0))) |
1364 insn_info->stack_pointer_based = true; | 1446 insn_info->stack_pointer_based = true; |
1366 | 1448 |
1367 store_info = cse_store_info_pool.allocate (); | 1449 store_info = cse_store_info_pool.allocate (); |
1368 group_id = -1; | 1450 group_id = -1; |
1369 | 1451 |
1370 if (dump_file && (dump_flags & TDF_DETAILS)) | 1452 if (dump_file && (dump_flags & TDF_DETAILS)) |
1371 fprintf (dump_file, " processing cselib store [%d..%d)\n", | 1453 { |
1372 (int)offset, (int)(offset+width)); | 1454 fprintf (dump_file, " processing cselib store "); |
1455 print_range (dump_file, offset, width); | |
1456 fprintf (dump_file, "\n"); | |
1457 } | |
1373 } | 1458 } |
1374 | 1459 |
1375 const_rhs = rhs = NULL_RTX; | 1460 const_rhs = rhs = NULL_RTX; |
1376 if (GET_CODE (body) == SET | 1461 if (GET_CODE (body) == SET |
1377 /* No place to keep the value after ra. */ | 1462 /* No place to keep the value after ra. */ |
1414 else | 1499 else |
1415 { | 1500 { |
1416 group_info *group = rtx_group_vec[group_id]; | 1501 group_info *group = rtx_group_vec[group_id]; |
1417 mem_addr = group->canon_base_addr; | 1502 mem_addr = group->canon_base_addr; |
1418 } | 1503 } |
1419 if (offset) | 1504 if (maybe_ne (offset, 0)) |
1420 mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); | 1505 mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); |
1421 | 1506 |
1422 while (ptr) | 1507 while (ptr) |
1423 { | 1508 { |
1424 insn_info_t next = ptr->next_local_store; | 1509 insn_info_t next = ptr->next_local_store; |
1433 | 1518 |
1434 if (s_info->group_id == group_id && s_info->cse_base == base) | 1519 if (s_info->group_id == group_id && s_info->cse_base == base) |
1435 { | 1520 { |
1436 HOST_WIDE_INT i; | 1521 HOST_WIDE_INT i; |
1437 if (dump_file && (dump_flags & TDF_DETAILS)) | 1522 if (dump_file && (dump_flags & TDF_DETAILS)) |
1438 fprintf (dump_file, " trying store in insn=%d gid=%d[%d..%d)\n", | 1523 { |
1439 INSN_UID (ptr->insn), s_info->group_id, | 1524 fprintf (dump_file, " trying store in insn=%d gid=%d", |
1440 (int)s_info->begin, (int)s_info->end); | 1525 INSN_UID (ptr->insn), s_info->group_id); |
1526 print_range (dump_file, s_info->offset, s_info->width); | |
1527 fprintf (dump_file, "\n"); | |
1528 } | |
1441 | 1529 |
1442 /* Even if PTR won't be eliminated as unneeded, if both | 1530 /* Even if PTR won't be eliminated as unneeded, if both |
1443 PTR and this insn store the same constant value, we might | 1531 PTR and this insn store the same constant value, we might |
1444 eliminate this insn instead. */ | 1532 eliminate this insn instead. */ |
1445 if (s_info->const_rhs | 1533 if (s_info->const_rhs |
1446 && const_rhs | 1534 && const_rhs |
1447 && offset >= s_info->begin | 1535 && known_subrange_p (offset, width, |
1448 && offset + width <= s_info->end | 1536 s_info->offset, s_info->width) |
1449 && all_positions_needed_p (s_info, offset - s_info->begin, | 1537 && all_positions_needed_p (s_info, offset - s_info->offset, |
1450 width)) | 1538 width) |
1539 /* We can only remove the later store if the earlier aliases | |
1540 at least all accesses the later one. */ | |
1541 && (MEM_ALIAS_SET (mem) == MEM_ALIAS_SET (s_info->mem) | |
1542 || alias_set_subset_of (MEM_ALIAS_SET (mem), | |
1543 MEM_ALIAS_SET (s_info->mem)))) | |
1451 { | 1544 { |
1452 if (GET_MODE (mem) == BLKmode) | 1545 if (GET_MODE (mem) == BLKmode) |
1453 { | 1546 { |
1454 if (GET_MODE (s_info->mem) == BLKmode | 1547 if (GET_MODE (s_info->mem) == BLKmode |
1455 && s_info->const_rhs == const_rhs) | 1548 && s_info->const_rhs == const_rhs) |
1460 redundant_reason = ptr; | 1553 redundant_reason = ptr; |
1461 else | 1554 else |
1462 { | 1555 { |
1463 rtx val; | 1556 rtx val; |
1464 start_sequence (); | 1557 start_sequence (); |
1465 val = get_stored_val (s_info, GET_MODE (mem), | 1558 val = get_stored_val (s_info, GET_MODE (mem), offset, width, |
1466 offset, offset + width, | |
1467 BLOCK_FOR_INSN (insn_info->insn), | 1559 BLOCK_FOR_INSN (insn_info->insn), |
1468 true); | 1560 true); |
1469 if (get_insns () != NULL) | 1561 if (get_insns () != NULL) |
1470 val = NULL_RTX; | 1562 val = NULL_RTX; |
1471 end_sequence (); | 1563 end_sequence (); |
1472 if (val && rtx_equal_p (val, const_rhs)) | 1564 if (val && rtx_equal_p (val, const_rhs)) |
1473 redundant_reason = ptr; | 1565 redundant_reason = ptr; |
1474 } | 1566 } |
1475 } | 1567 } |
1476 | 1568 |
1477 for (i = MAX (offset, s_info->begin); | 1569 HOST_WIDE_INT begin_unneeded, const_s_width, const_width; |
1478 i < offset + width && i < s_info->end; | 1570 if (known_subrange_p (s_info->offset, s_info->width, offset, width)) |
1479 i++) | 1571 /* The new store touches every byte that S_INFO does. */ |
1480 set_position_unneeded (s_info, i - s_info->begin); | 1572 set_all_positions_unneeded (s_info); |
1573 else if ((offset - s_info->offset).is_constant (&begin_unneeded) | |
1574 && s_info->width.is_constant (&const_s_width) | |
1575 && width.is_constant (&const_width)) | |
1576 { | |
1577 HOST_WIDE_INT end_unneeded = begin_unneeded + const_width; | |
1578 begin_unneeded = MAX (begin_unneeded, 0); | |
1579 end_unneeded = MIN (end_unneeded, const_s_width); | |
1580 for (i = begin_unneeded; i < end_unneeded; ++i) | |
1581 set_position_unneeded (s_info, i); | |
1582 } | |
1583 else | |
1584 { | |
1585 /* We don't know which parts of S_INFO are needed and | |
1586 which aren't, so invalidate the RHS. */ | |
1587 s_info->rhs = NULL; | |
1588 s_info->const_rhs = NULL; | |
1589 } | |
1481 } | 1590 } |
1482 else if (s_info->rhs) | 1591 else if (s_info->rhs) |
1483 /* Need to see if it is possible for this store to overwrite | 1592 /* Need to see if it is possible for this store to overwrite |
1484 the value of store_info. If it is, set the rhs to NULL to | 1593 the value of store_info. If it is, set the rhs to NULL to |
1485 keep it from being used to remove a load. */ | 1594 keep it from being used to remove a load. */ |
1521 store_info->next = insn_info->store_rec; | 1630 store_info->next = insn_info->store_rec; |
1522 insn_info->store_rec = store_info; | 1631 insn_info->store_rec = store_info; |
1523 store_info->mem = mem; | 1632 store_info->mem = mem; |
1524 store_info->mem_addr = mem_addr; | 1633 store_info->mem_addr = mem_addr; |
1525 store_info->cse_base = base; | 1634 store_info->cse_base = base; |
1526 if (width > HOST_BITS_PER_WIDE_INT) | 1635 HOST_WIDE_INT const_width; |
1636 if (!width.is_constant (&const_width)) | |
1637 { | |
1638 store_info->is_large = true; | |
1639 store_info->positions_needed.large.count = 0; | |
1640 store_info->positions_needed.large.bmap = NULL; | |
1641 } | |
1642 else if (const_width > HOST_BITS_PER_WIDE_INT) | |
1527 { | 1643 { |
1528 store_info->is_large = true; | 1644 store_info->is_large = true; |
1529 store_info->positions_needed.large.count = 0; | 1645 store_info->positions_needed.large.count = 0; |
1530 store_info->positions_needed.large.bmap = BITMAP_ALLOC (&dse_bitmap_obstack); | 1646 store_info->positions_needed.large.bmap = BITMAP_ALLOC (&dse_bitmap_obstack); |
1531 } | 1647 } |
1532 else | 1648 else |
1533 { | 1649 { |
1534 store_info->is_large = false; | 1650 store_info->is_large = false; |
1535 store_info->positions_needed.small_bitmask = lowpart_bitmask (width); | 1651 store_info->positions_needed.small_bitmask |
1652 = lowpart_bitmask (const_width); | |
1536 } | 1653 } |
1537 store_info->group_id = group_id; | 1654 store_info->group_id = group_id; |
1538 store_info->begin = offset; | 1655 store_info->offset = offset; |
1539 store_info->end = offset + width; | 1656 store_info->width = width; |
1540 store_info->is_set = GET_CODE (body) == SET; | 1657 store_info->is_set = GET_CODE (body) == SET; |
1541 store_info->rhs = rhs; | 1658 store_info->rhs = rhs; |
1542 store_info->const_rhs = const_rhs; | 1659 store_info->const_rhs = const_rhs; |
1543 store_info->redundant_reason = redundant_reason; | 1660 store_info->redundant_reason = redundant_reason; |
1544 | 1661 |
1565 value that is at least ACCESS_SIZE bytes wide of READ_MODE. The | 1682 value that is at least ACCESS_SIZE bytes wide of READ_MODE. The |
1566 shift sequence is returned or NULL if we failed to find a | 1683 shift sequence is returned or NULL if we failed to find a |
1567 shift. */ | 1684 shift. */ |
1568 | 1685 |
1569 static rtx | 1686 static rtx |
1570 find_shift_sequence (int access_size, | 1687 find_shift_sequence (poly_int64 access_size, |
1571 store_info *store_info, | 1688 store_info *store_info, |
1572 machine_mode read_mode, | 1689 machine_mode read_mode, |
1573 int shift, bool speed, bool require_cst) | 1690 poly_int64 shift, bool speed, bool require_cst) |
1574 { | 1691 { |
1575 machine_mode store_mode = GET_MODE (store_info->mem); | 1692 machine_mode store_mode = GET_MODE (store_info->mem); |
1576 scalar_int_mode new_mode; | 1693 scalar_int_mode new_mode; |
1577 rtx read_reg = NULL; | 1694 rtx read_reg = NULL; |
1578 | 1695 |
1598 /* If a constant was stored into memory, try to simplify it here, | 1715 /* If a constant was stored into memory, try to simplify it here, |
1599 otherwise the cost of the shift might preclude this optimization | 1716 otherwise the cost of the shift might preclude this optimization |
1600 e.g. at -Os, even when no actual shift will be needed. */ | 1717 e.g. at -Os, even when no actual shift will be needed. */ |
1601 if (store_info->const_rhs) | 1718 if (store_info->const_rhs) |
1602 { | 1719 { |
1603 unsigned int byte = subreg_lowpart_offset (new_mode, store_mode); | 1720 poly_uint64 byte = subreg_lowpart_offset (new_mode, store_mode); |
1604 rtx ret = simplify_subreg (new_mode, store_info->const_rhs, | 1721 rtx ret = simplify_subreg (new_mode, store_info->const_rhs, |
1605 store_mode, byte); | 1722 store_mode, byte); |
1606 if (ret && CONSTANT_P (ret)) | 1723 if (ret && CONSTANT_P (ret)) |
1607 { | 1724 { |
1725 rtx shift_rtx = gen_int_shift_amount (new_mode, shift); | |
1608 ret = simplify_const_binary_operation (LSHIFTRT, new_mode, | 1726 ret = simplify_const_binary_operation (LSHIFTRT, new_mode, |
1609 ret, GEN_INT (shift)); | 1727 ret, shift_rtx); |
1610 if (ret && CONSTANT_P (ret)) | 1728 if (ret && CONSTANT_P (ret)) |
1611 { | 1729 { |
1612 byte = subreg_lowpart_offset (read_mode, new_mode); | 1730 byte = subreg_lowpart_offset (read_mode, new_mode); |
1613 ret = simplify_subreg (read_mode, ret, new_mode, byte); | 1731 ret = simplify_subreg (read_mode, ret, new_mode, byte); |
1614 if (ret && CONSTANT_P (ret) | 1732 if (ret && CONSTANT_P (ret) |
1622 if (require_cst) | 1740 if (require_cst) |
1623 return NULL_RTX; | 1741 return NULL_RTX; |
1624 | 1742 |
1625 /* Try a wider mode if truncating the store mode to NEW_MODE | 1743 /* Try a wider mode if truncating the store mode to NEW_MODE |
1626 requires a real instruction. */ | 1744 requires a real instruction. */ |
1627 if (GET_MODE_BITSIZE (new_mode) < GET_MODE_BITSIZE (store_mode) | 1745 if (maybe_lt (GET_MODE_SIZE (new_mode), GET_MODE_SIZE (store_mode)) |
1628 && !TRULY_NOOP_TRUNCATION_MODES_P (new_mode, store_mode)) | 1746 && !TRULY_NOOP_TRUNCATION_MODES_P (new_mode, store_mode)) |
1629 continue; | 1747 continue; |
1630 | 1748 |
1631 /* Also try a wider mode if the necessary punning is either not | 1749 /* Also try a wider mode if the necessary punning is either not |
1632 desirable or not possible. */ | 1750 desirable or not possible. */ |
1640 | 1758 |
1641 /* In theory we could also check for an ashr. Ian Taylor knows | 1759 /* In theory we could also check for an ashr. Ian Taylor knows |
1642 of one dsp where the cost of these two was not the same. But | 1760 of one dsp where the cost of these two was not the same. But |
1643 this really is a rare case anyway. */ | 1761 this really is a rare case anyway. */ |
1644 target = expand_binop (new_mode, lshr_optab, new_reg, | 1762 target = expand_binop (new_mode, lshr_optab, new_reg, |
1645 GEN_INT (shift), new_reg, 1, OPTAB_DIRECT); | 1763 gen_int_shift_amount (new_mode, shift), |
1764 new_reg, 1, OPTAB_DIRECT); | |
1646 | 1765 |
1647 shift_seq = get_insns (); | 1766 shift_seq = get_insns (); |
1648 end_sequence (); | 1767 end_sequence (); |
1649 | 1768 |
1650 if (target != new_reg || shift_seq == NULL) | 1769 if (target != new_reg || shift_seq == NULL) |
1696 && HARD_REGISTER_P (x)) | 1815 && HARD_REGISTER_P (x)) |
1697 bitmap_set_range (regs_set, REGNO (x), REG_NREGS (x)); | 1816 bitmap_set_range (regs_set, REGNO (x), REG_NREGS (x)); |
1698 } | 1817 } |
1699 | 1818 |
1700 /* Helper function for replace_read and record_store. | 1819 /* Helper function for replace_read and record_store. |
1701 Attempt to return a value stored in STORE_INFO, from READ_BEGIN | 1820 Attempt to return a value of mode READ_MODE stored in STORE_INFO, |
1702 to one before READ_END bytes read in READ_MODE. Return NULL | 1821 consisting of READ_WIDTH bytes starting from READ_OFFSET. Return NULL |
1703 if not successful. If REQUIRE_CST is true, return always constant. */ | 1822 if not successful. If REQUIRE_CST is true, return always constant. */ |
1704 | 1823 |
1705 static rtx | 1824 static rtx |
1706 get_stored_val (store_info *store_info, machine_mode read_mode, | 1825 get_stored_val (store_info *store_info, machine_mode read_mode, |
1707 HOST_WIDE_INT read_begin, HOST_WIDE_INT read_end, | 1826 poly_int64 read_offset, poly_int64 read_width, |
1708 basic_block bb, bool require_cst) | 1827 basic_block bb, bool require_cst) |
1709 { | 1828 { |
1710 machine_mode store_mode = GET_MODE (store_info->mem); | 1829 machine_mode store_mode = GET_MODE (store_info->mem); |
1711 int shift; | 1830 poly_int64 gap; |
1712 int access_size; /* In bytes. */ | |
1713 rtx read_reg; | 1831 rtx read_reg; |
1714 | 1832 |
1715 /* To get here the read is within the boundaries of the write so | 1833 /* To get here the read is within the boundaries of the write so |
1716 shift will never be negative. Start out with the shift being in | 1834 shift will never be negative. Start out with the shift being in |
1717 bytes. */ | 1835 bytes. */ |
1718 if (store_mode == BLKmode) | 1836 if (store_mode == BLKmode) |
1719 shift = 0; | 1837 gap = 0; |
1720 else if (BYTES_BIG_ENDIAN) | 1838 else if (BYTES_BIG_ENDIAN) |
1721 shift = store_info->end - read_end; | 1839 gap = ((store_info->offset + store_info->width) |
1840 - (read_offset + read_width)); | |
1722 else | 1841 else |
1723 shift = read_begin - store_info->begin; | 1842 gap = read_offset - store_info->offset; |
1724 | 1843 |
1725 access_size = shift + GET_MODE_SIZE (read_mode); | 1844 if (maybe_ne (gap, 0)) |
1726 | 1845 { |
1727 /* From now on it is bits. */ | 1846 poly_int64 shift = gap * BITS_PER_UNIT; |
1728 shift *= BITS_PER_UNIT; | 1847 poly_int64 access_size = GET_MODE_SIZE (read_mode) + gap; |
1729 | 1848 read_reg = find_shift_sequence (access_size, store_info, read_mode, |
1730 if (shift) | 1849 shift, optimize_bb_for_speed_p (bb), |
1731 read_reg = find_shift_sequence (access_size, store_info, read_mode, shift, | 1850 require_cst); |
1732 optimize_bb_for_speed_p (bb), | 1851 } |
1733 require_cst); | |
1734 else if (store_mode == BLKmode) | 1852 else if (store_mode == BLKmode) |
1735 { | 1853 { |
1736 /* The store is a memset (addr, const_val, const_size). */ | 1854 /* The store is a memset (addr, const_val, const_size). */ |
1737 gcc_assert (CONST_INT_P (store_info->rhs)); | 1855 gcc_assert (CONST_INT_P (store_info->rhs)); |
1738 scalar_int_mode int_store_mode; | 1856 scalar_int_mode int_store_mode; |
1831 GET_MODE_NAME (read_mode), INSN_UID (read_insn->insn), | 1949 GET_MODE_NAME (read_mode), INSN_UID (read_insn->insn), |
1832 GET_MODE_NAME (store_mode), INSN_UID (store_insn->insn)); | 1950 GET_MODE_NAME (store_mode), INSN_UID (store_insn->insn)); |
1833 start_sequence (); | 1951 start_sequence (); |
1834 bb = BLOCK_FOR_INSN (read_insn->insn); | 1952 bb = BLOCK_FOR_INSN (read_insn->insn); |
1835 read_reg = get_stored_val (store_info, | 1953 read_reg = get_stored_val (store_info, |
1836 read_mode, read_info->begin, read_info->end, | 1954 read_mode, read_info->offset, read_info->width, |
1837 bb, false); | 1955 bb, false); |
1838 if (read_reg == NULL_RTX) | 1956 if (read_reg == NULL_RTX) |
1839 { | 1957 { |
1840 end_sequence (); | 1958 end_sequence (); |
1841 if (dump_file && (dump_flags & TDF_DETAILS)) | 1959 if (dump_file && (dump_flags & TDF_DETAILS)) |
1943 static void | 2061 static void |
1944 check_mem_read_rtx (rtx *loc, bb_info_t bb_info) | 2062 check_mem_read_rtx (rtx *loc, bb_info_t bb_info) |
1945 { | 2063 { |
1946 rtx mem = *loc, mem_addr; | 2064 rtx mem = *loc, mem_addr; |
1947 insn_info_t insn_info; | 2065 insn_info_t insn_info; |
1948 HOST_WIDE_INT offset = 0; | 2066 poly_int64 offset = 0; |
1949 HOST_WIDE_INT width = 0; | 2067 poly_int64 width = 0; |
1950 cselib_val *base = NULL; | 2068 cselib_val *base = NULL; |
1951 int group_id; | 2069 int group_id; |
1952 read_info_t read_info; | 2070 read_info_t read_info; |
1953 | 2071 |
1954 insn_info = bb_info->last_insn; | 2072 insn_info = bb_info->last_insn; |
1979 if (GET_MODE (mem) == BLKmode) | 2097 if (GET_MODE (mem) == BLKmode) |
1980 width = -1; | 2098 width = -1; |
1981 else | 2099 else |
1982 width = GET_MODE_SIZE (GET_MODE (mem)); | 2100 width = GET_MODE_SIZE (GET_MODE (mem)); |
1983 | 2101 |
2102 if (!endpoint_representable_p (offset, known_eq (width, -1) ? 1 : width)) | |
2103 { | |
2104 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2105 fprintf (dump_file, " adding wild read, due to overflow.\n"); | |
2106 add_wild_read (bb_info); | |
2107 return; | |
2108 } | |
2109 | |
1984 read_info = read_info_type_pool.allocate (); | 2110 read_info = read_info_type_pool.allocate (); |
1985 read_info->group_id = group_id; | 2111 read_info->group_id = group_id; |
1986 read_info->mem = mem; | 2112 read_info->mem = mem; |
1987 read_info->begin = offset; | 2113 read_info->offset = offset; |
1988 read_info->end = offset + width; | 2114 read_info->width = width; |
1989 read_info->next = insn_info->read_rec; | 2115 read_info->next = insn_info->read_rec; |
1990 insn_info->read_rec = read_info; | 2116 insn_info->read_rec = read_info; |
1991 if (group_id < 0) | 2117 if (group_id < 0) |
1992 mem_addr = base->val_rtx; | 2118 mem_addr = base->val_rtx; |
1993 else | 2119 else |
1994 { | 2120 { |
1995 group_info *group = rtx_group_vec[group_id]; | 2121 group_info *group = rtx_group_vec[group_id]; |
1996 mem_addr = group->canon_base_addr; | 2122 mem_addr = group->canon_base_addr; |
1997 } | 2123 } |
1998 if (offset) | 2124 if (maybe_ne (offset, 0)) |
1999 mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); | 2125 mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); |
2000 | 2126 |
2001 if (group_id >= 0) | 2127 if (group_id >= 0) |
2002 { | 2128 { |
2003 /* This is the restricted case where the base is a constant or | 2129 /* This is the restricted case where the base is a constant or |
2005 insn_info_t i_ptr = active_local_stores; | 2131 insn_info_t i_ptr = active_local_stores; |
2006 insn_info_t last = NULL; | 2132 insn_info_t last = NULL; |
2007 | 2133 |
2008 if (dump_file && (dump_flags & TDF_DETAILS)) | 2134 if (dump_file && (dump_flags & TDF_DETAILS)) |
2009 { | 2135 { |
2010 if (width == -1) | 2136 if (!known_size_p (width)) |
2011 fprintf (dump_file, " processing const load gid=%d[BLK]\n", | 2137 fprintf (dump_file, " processing const load gid=%d[BLK]\n", |
2012 group_id); | 2138 group_id); |
2013 else | 2139 else |
2014 fprintf (dump_file, " processing const load gid=%d[%d..%d)\n", | 2140 { |
2015 group_id, (int)offset, (int)(offset+width)); | 2141 fprintf (dump_file, " processing const load gid=%d", group_id); |
2142 print_range (dump_file, offset, width); | |
2143 fprintf (dump_file, "\n"); | |
2144 } | |
2016 } | 2145 } |
2017 | 2146 |
2018 while (i_ptr) | 2147 while (i_ptr) |
2019 { | 2148 { |
2020 bool remove = false; | 2149 bool remove = false; |
2036 | 2165 |
2037 else if (group_id == store_info->group_id) | 2166 else if (group_id == store_info->group_id) |
2038 { | 2167 { |
2039 /* This is a block mode load. We may get lucky and | 2168 /* This is a block mode load. We may get lucky and |
2040 canon_true_dependence may save the day. */ | 2169 canon_true_dependence may save the day. */ |
2041 if (width == -1) | 2170 if (!known_size_p (width)) |
2042 remove | 2171 remove |
2043 = canon_true_dependence (store_info->mem, | 2172 = canon_true_dependence (store_info->mem, |
2044 GET_MODE (store_info->mem), | 2173 GET_MODE (store_info->mem), |
2045 store_info->mem_addr, | 2174 store_info->mem_addr, |
2046 mem, mem_addr); | 2175 mem, mem_addr); |
2048 /* If this read is just reading back something that we just | 2177 /* If this read is just reading back something that we just |
2049 stored, rewrite the read. */ | 2178 stored, rewrite the read. */ |
2050 else | 2179 else |
2051 { | 2180 { |
2052 if (store_info->rhs | 2181 if (store_info->rhs |
2053 && offset >= store_info->begin | 2182 && known_subrange_p (offset, width, store_info->offset, |
2054 && offset + width <= store_info->end | 2183 store_info->width) |
2055 && all_positions_needed_p (store_info, | 2184 && all_positions_needed_p (store_info, |
2056 offset - store_info->begin, | 2185 offset - store_info->offset, |
2057 width) | 2186 width) |
2058 && replace_read (store_info, i_ptr, read_info, | 2187 && replace_read (store_info, i_ptr, read_info, |
2059 insn_info, loc, bb_info->regs_live)) | 2188 insn_info, loc, bb_info->regs_live)) |
2060 return; | 2189 return; |
2061 | 2190 |
2062 /* The bases are the same, just see if the offsets | 2191 /* The bases are the same, just see if the offsets |
2063 overlap. */ | 2192 could overlap. */ |
2064 if ((offset < store_info->end) | 2193 if (ranges_maybe_overlap_p (offset, width, |
2065 && (offset + width > store_info->begin)) | 2194 store_info->offset, |
2195 store_info->width)) | |
2066 remove = true; | 2196 remove = true; |
2067 } | 2197 } |
2068 } | 2198 } |
2069 | 2199 |
2070 /* else | 2200 /* else |
2115 /* If this read is just reading back something that we just | 2245 /* If this read is just reading back something that we just |
2116 stored, rewrite the read. */ | 2246 stored, rewrite the read. */ |
2117 if (store_info->rhs | 2247 if (store_info->rhs |
2118 && store_info->group_id == -1 | 2248 && store_info->group_id == -1 |
2119 && store_info->cse_base == base | 2249 && store_info->cse_base == base |
2120 && width != -1 | 2250 && known_subrange_p (offset, width, store_info->offset, |
2121 && offset >= store_info->begin | 2251 store_info->width) |
2122 && offset + width <= store_info->end | |
2123 && all_positions_needed_p (store_info, | 2252 && all_positions_needed_p (store_info, |
2124 offset - store_info->begin, width) | 2253 offset - store_info->offset, width) |
2125 && replace_read (store_info, i_ptr, read_info, insn_info, loc, | 2254 && replace_read (store_info, i_ptr, read_info, insn_info, loc, |
2126 bb_info->regs_live)) | 2255 bb_info->regs_live)) |
2127 return; | 2256 return; |
2128 | 2257 |
2129 remove = canon_true_dependence (store_info->mem, | 2258 remove = canon_true_dependence (store_info->mem, |
2288 && (call = get_call_rtx_from (insn)) | 2417 && (call = get_call_rtx_from (insn)) |
2289 && (sym = XEXP (XEXP (call, 0), 0)) | 2418 && (sym = XEXP (XEXP (call, 0), 0)) |
2290 && GET_CODE (sym) == SYMBOL_REF | 2419 && GET_CODE (sym) == SYMBOL_REF |
2291 && SYMBOL_REF_DECL (sym) | 2420 && SYMBOL_REF_DECL (sym) |
2292 && TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL | 2421 && TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL |
2293 && DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (sym)) == BUILT_IN_NORMAL | 2422 && fndecl_built_in_p (SYMBOL_REF_DECL (sym), BUILT_IN_MEMSET)) |
2294 && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (sym)) == BUILT_IN_MEMSET) | |
2295 memset_call = SYMBOL_REF_DECL (sym); | 2423 memset_call = SYMBOL_REF_DECL (sym); |
2296 | 2424 |
2297 if (const_call || memset_call) | 2425 if (const_call || memset_call) |
2298 { | 2426 { |
2299 insn_info_t i_ptr = active_local_stores; | 2427 insn_info_t i_ptr = active_local_stores; |
2767 static void | 2895 static void |
2768 scan_stores (store_info *store_info, bitmap gen, bitmap kill) | 2896 scan_stores (store_info *store_info, bitmap gen, bitmap kill) |
2769 { | 2897 { |
2770 while (store_info) | 2898 while (store_info) |
2771 { | 2899 { |
2772 HOST_WIDE_INT i; | 2900 HOST_WIDE_INT i, offset, width; |
2773 group_info *group_info | 2901 group_info *group_info |
2774 = rtx_group_vec[store_info->group_id]; | 2902 = rtx_group_vec[store_info->group_id]; |
2775 if (group_info->process_globally) | 2903 /* We can (conservatively) ignore stores whose bounds aren't known; |
2776 for (i = store_info->begin; i < store_info->end; i++) | 2904 they simply don't generate new global dse opportunities. */ |
2777 { | 2905 if (group_info->process_globally |
2778 int index = get_bitmap_index (group_info, i); | 2906 && store_info->offset.is_constant (&offset) |
2779 if (index != 0) | 2907 && store_info->width.is_constant (&width)) |
2780 { | 2908 { |
2781 bitmap_set_bit (gen, index); | 2909 HOST_WIDE_INT end = offset + width; |
2782 if (kill) | 2910 for (i = offset; i < end; i++) |
2783 bitmap_clear_bit (kill, index); | 2911 { |
2784 } | 2912 int index = get_bitmap_index (group_info, i); |
2785 } | 2913 if (index != 0) |
2914 { | |
2915 bitmap_set_bit (gen, index); | |
2916 if (kill) | |
2917 bitmap_clear_bit (kill, index); | |
2918 } | |
2919 } | |
2920 } | |
2786 store_info = store_info->next; | 2921 store_info = store_info->next; |
2787 } | 2922 } |
2788 } | 2923 } |
2789 | 2924 |
2790 | 2925 |
2830 { | 2965 { |
2831 if (group->process_globally) | 2966 if (group->process_globally) |
2832 { | 2967 { |
2833 if (i == read_info->group_id) | 2968 if (i == read_info->group_id) |
2834 { | 2969 { |
2835 if (read_info->begin > read_info->end) | 2970 HOST_WIDE_INT offset, width; |
2971 /* Reads with non-constant size kill all DSE opportunities | |
2972 in the group. */ | |
2973 if (!read_info->offset.is_constant (&offset) | |
2974 || !read_info->width.is_constant (&width) | |
2975 || !known_size_p (width)) | |
2836 { | 2976 { |
2837 /* Begin > end for block mode reads. */ | 2977 /* Handle block mode reads. */ |
2838 if (kill) | 2978 if (kill) |
2839 bitmap_ior_into (kill, group->group_kill); | 2979 bitmap_ior_into (kill, group->group_kill); |
2840 bitmap_and_compl_into (gen, group->group_kill); | 2980 bitmap_and_compl_into (gen, group->group_kill); |
2841 } | 2981 } |
2842 else | 2982 else |
2843 { | 2983 { |
2844 /* The groups are the same, just process the | 2984 /* The groups are the same, just process the |
2845 offsets. */ | 2985 offsets. */ |
2846 HOST_WIDE_INT j; | 2986 HOST_WIDE_INT j; |
2847 for (j = read_info->begin; j < read_info->end; j++) | 2987 HOST_WIDE_INT end = offset + width; |
2988 for (j = offset; j < end; j++) | |
2848 { | 2989 { |
2849 int index = get_bitmap_index (group, j); | 2990 int index = get_bitmap_index (group, j); |
2850 if (index != 0) | 2991 if (index != 0) |
2851 { | 2992 { |
2852 if (kill) | 2993 if (kill) |
3258 | 3399 |
3259 /* Skip the clobbers. */ | 3400 /* Skip the clobbers. */ |
3260 while (!store_info->is_set) | 3401 while (!store_info->is_set) |
3261 store_info = store_info->next; | 3402 store_info = store_info->next; |
3262 | 3403 |
3263 HOST_WIDE_INT i; | 3404 HOST_WIDE_INT i, offset, width; |
3264 group_info *group_info = rtx_group_vec[store_info->group_id]; | 3405 group_info *group_info = rtx_group_vec[store_info->group_id]; |
3265 | 3406 |
3266 for (i = store_info->begin; i < store_info->end; i++) | 3407 if (!store_info->offset.is_constant (&offset) |
3408 || !store_info->width.is_constant (&width)) | |
3409 deleted = false; | |
3410 else | |
3267 { | 3411 { |
3268 int index = get_bitmap_index (group_info, i); | 3412 HOST_WIDE_INT end = offset + width; |
3269 | 3413 for (i = offset; i < end; i++) |
3270 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3271 fprintf (dump_file, "i = %d, index = %d\n", (int)i, index); | |
3272 if (index == 0 || !bitmap_bit_p (v, index)) | |
3273 { | 3414 { |
3415 int index = get_bitmap_index (group_info, i); | |
3416 | |
3274 if (dump_file && (dump_flags & TDF_DETAILS)) | 3417 if (dump_file && (dump_flags & TDF_DETAILS)) |
3275 fprintf (dump_file, "failing at i = %d\n", (int)i); | 3418 fprintf (dump_file, "i = %d, index = %d\n", |
3276 deleted = false; | 3419 (int) i, index); |
3277 break; | 3420 if (index == 0 || !bitmap_bit_p (v, index)) |
3421 { | |
3422 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3423 fprintf (dump_file, "failing at i = %d\n", | |
3424 (int) i); | |
3425 deleted = false; | |
3426 break; | |
3427 } | |
3278 } | 3428 } |
3279 } | 3429 } |
3280 if (deleted) | 3430 if (deleted) |
3281 { | 3431 { |
3282 if (dbg_cnt (dse) | 3432 if (dbg_cnt (dse) |