Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-ssa-math-opts.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
95 #include "timevar.h" | 95 #include "timevar.h" |
96 #include "tree-pass.h" | 96 #include "tree-pass.h" |
97 #include "alloc-pool.h" | 97 #include "alloc-pool.h" |
98 #include "basic-block.h" | 98 #include "basic-block.h" |
99 #include "target.h" | 99 #include "target.h" |
100 #include "diagnostic.h" | |
101 #include "gimple-pretty-print.h" | 100 #include "gimple-pretty-print.h" |
102 | 101 |
103 /* FIXME: RTL headers have to be included here for optabs. */ | 102 /* FIXME: RTL headers have to be included here for optabs. */ |
104 #include "rtl.h" /* Because optabs.h wants enum rtx_code. */ | 103 #include "rtl.h" /* Because optabs.h wants enum rtx_code. */ |
105 #include "expr.h" /* Because optabs.h wants sepops. */ | 104 #include "expr.h" /* Because optabs.h wants sepops. */ |
473 #ifdef ENABLE_CHECKING | 472 #ifdef ENABLE_CHECKING |
474 FOR_EACH_BB (bb) | 473 FOR_EACH_BB (bb) |
475 gcc_assert (!bb->aux); | 474 gcc_assert (!bb->aux); |
476 #endif | 475 #endif |
477 | 476 |
478 for (arg = DECL_ARGUMENTS (cfun->decl); arg; arg = TREE_CHAIN (arg)) | 477 for (arg = DECL_ARGUMENTS (cfun->decl); arg; arg = DECL_CHAIN (arg)) |
479 if (gimple_default_def (cfun, arg) | 478 if (gimple_default_def (cfun, arg) |
480 && FLOAT_TYPE_P (TREE_TYPE (arg)) | 479 && FLOAT_TYPE_P (TREE_TYPE (arg)) |
481 && is_gimple_reg (arg)) | 480 && is_gimple_reg (arg)) |
482 execute_cse_reciprocals_1 (NULL, gimple_default_def (cfun, arg)); | 481 execute_cse_reciprocals_1 (NULL, gimple_default_def (cfun, arg)); |
483 | 482 |
640 statements that we can CSE in a vector and in a second pass replace | 639 statements that we can CSE in a vector and in a second pass replace |
641 the statement rhs with a REALPART or IMAGPART expression on the | 640 the statement rhs with a REALPART or IMAGPART expression on the |
642 result of the cexpi call we insert before the use statement that | 641 result of the cexpi call we insert before the use statement that |
643 dominates all other candidates. */ | 642 dominates all other candidates. */ |
644 | 643 |
645 static void | 644 static bool |
646 execute_cse_sincos_1 (tree name) | 645 execute_cse_sincos_1 (tree name) |
647 { | 646 { |
648 gimple_stmt_iterator gsi; | 647 gimple_stmt_iterator gsi; |
649 imm_use_iterator use_iter; | 648 imm_use_iterator use_iter; |
650 tree fndecl, res, type; | 649 tree fndecl, res, type; |
651 gimple def_stmt, use_stmt, stmt; | 650 gimple def_stmt, use_stmt, stmt; |
652 int seen_cos = 0, seen_sin = 0, seen_cexpi = 0; | 651 int seen_cos = 0, seen_sin = 0, seen_cexpi = 0; |
653 VEC(gimple, heap) *stmts = NULL; | 652 VEC(gimple, heap) *stmts = NULL; |
654 basic_block top_bb = NULL; | 653 basic_block top_bb = NULL; |
655 int i; | 654 int i; |
655 bool cfg_changed = false; | |
656 | 656 |
657 type = TREE_TYPE (name); | 657 type = TREE_TYPE (name); |
658 FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name) | 658 FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name) |
659 { | 659 { |
660 if (gimple_code (use_stmt) != GIMPLE_CALL | 660 if (gimple_code (use_stmt) != GIMPLE_CALL |
682 } | 682 } |
683 | 683 |
684 if (seen_cos + seen_sin + seen_cexpi <= 1) | 684 if (seen_cos + seen_sin + seen_cexpi <= 1) |
685 { | 685 { |
686 VEC_free(gimple, heap, stmts); | 686 VEC_free(gimple, heap, stmts); |
687 return; | 687 return false; |
688 } | 688 } |
689 | 689 |
690 /* Simply insert cexpi at the beginning of top_bb but not earlier than | 690 /* Simply insert cexpi at the beginning of top_bb but not earlier than |
691 the name def statement. */ | 691 the name def statement. */ |
692 fndecl = mathfn_built_in (type, BUILT_IN_CEXPI); | 692 fndecl = mathfn_built_in (type, BUILT_IN_CEXPI); |
693 if (!fndecl) | 693 if (!fndecl) |
694 return; | 694 return false; |
695 res = make_rename_temp (TREE_TYPE (TREE_TYPE (fndecl)), "sincostmp"); | 695 res = create_tmp_reg (TREE_TYPE (TREE_TYPE (fndecl)), "sincostmp"); |
696 stmt = gimple_build_call (fndecl, 1, name); | 696 stmt = gimple_build_call (fndecl, 1, name); |
697 res = make_ssa_name (res, stmt); | |
697 gimple_call_set_lhs (stmt, res); | 698 gimple_call_set_lhs (stmt, res); |
698 | 699 |
699 def_stmt = SSA_NAME_DEF_STMT (name); | 700 def_stmt = SSA_NAME_DEF_STMT (name); |
700 if (!SSA_NAME_IS_DEFAULT_DEF (name) | 701 if (!SSA_NAME_IS_DEFAULT_DEF (name) |
701 && gimple_code (def_stmt) != GIMPLE_PHI | 702 && gimple_code (def_stmt) != GIMPLE_PHI |
737 | 738 |
738 /* Replace call with a copy. */ | 739 /* Replace call with a copy. */ |
739 stmt = gimple_build_assign (gimple_call_lhs (use_stmt), rhs); | 740 stmt = gimple_build_assign (gimple_call_lhs (use_stmt), rhs); |
740 | 741 |
741 gsi = gsi_for_stmt (use_stmt); | 742 gsi = gsi_for_stmt (use_stmt); |
742 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); | 743 gsi_replace (&gsi, stmt, true); |
743 gsi_remove (&gsi, true); | 744 if (gimple_purge_dead_eh_edges (gimple_bb (stmt))) |
745 cfg_changed = true; | |
744 } | 746 } |
745 | 747 |
746 VEC_free(gimple, heap, stmts); | 748 VEC_free(gimple, heap, stmts); |
749 | |
750 return cfg_changed; | |
747 } | 751 } |
748 | 752 |
749 /* Go through all calls to sin, cos and cexpi and call execute_cse_sincos_1 | 753 /* Go through all calls to sin, cos and cexpi and call execute_cse_sincos_1 |
750 on the SSA_NAME argument of each of them. */ | 754 on the SSA_NAME argument of each of them. */ |
751 | 755 |
752 static unsigned int | 756 static unsigned int |
753 execute_cse_sincos (void) | 757 execute_cse_sincos (void) |
754 { | 758 { |
755 basic_block bb; | 759 basic_block bb; |
760 bool cfg_changed = false; | |
756 | 761 |
757 calculate_dominance_info (CDI_DOMINATORS); | 762 calculate_dominance_info (CDI_DOMINATORS); |
758 | 763 |
759 FOR_EACH_BB (bb) | 764 FOR_EACH_BB (bb) |
760 { | 765 { |
777 CASE_FLT_FN (BUILT_IN_COS): | 782 CASE_FLT_FN (BUILT_IN_COS): |
778 CASE_FLT_FN (BUILT_IN_SIN): | 783 CASE_FLT_FN (BUILT_IN_SIN): |
779 CASE_FLT_FN (BUILT_IN_CEXPI): | 784 CASE_FLT_FN (BUILT_IN_CEXPI): |
780 arg = gimple_call_arg (stmt, 0); | 785 arg = gimple_call_arg (stmt, 0); |
781 if (TREE_CODE (arg) == SSA_NAME) | 786 if (TREE_CODE (arg) == SSA_NAME) |
782 execute_cse_sincos_1 (arg); | 787 cfg_changed |= execute_cse_sincos_1 (arg); |
783 break; | 788 break; |
784 | 789 |
785 default:; | 790 default:; |
786 } | 791 } |
787 } | 792 } |
788 } | 793 } |
789 } | 794 } |
790 | 795 |
791 free_dominance_info (CDI_DOMINATORS); | 796 free_dominance_info (CDI_DOMINATORS); |
792 return 0; | 797 return cfg_changed ? TODO_cleanup_cfg : 0; |
793 } | 798 } |
794 | 799 |
795 static bool | 800 static bool |
796 gate_cse_sincos (void) | 801 gate_cse_sincos (void) |
797 { | 802 { |
1112 | 1117 |
1113 if (sizeof (HOST_WIDEST_INT) < 8) | 1118 if (sizeof (HOST_WIDEST_INT) < 8) |
1114 return 0; | 1119 return 0; |
1115 | 1120 |
1116 bswap32_p = (built_in_decls[BUILT_IN_BSWAP32] | 1121 bswap32_p = (built_in_decls[BUILT_IN_BSWAP32] |
1117 && optab_handler (bswap_optab, SImode)->insn_code != | 1122 && optab_handler (bswap_optab, SImode) != CODE_FOR_nothing); |
1118 CODE_FOR_nothing); | |
1119 bswap64_p = (built_in_decls[BUILT_IN_BSWAP64] | 1123 bswap64_p = (built_in_decls[BUILT_IN_BSWAP64] |
1120 && (optab_handler (bswap_optab, DImode)->insn_code != | 1124 && (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing |
1121 CODE_FOR_nothing | |
1122 || (bswap32_p && word_mode == SImode))); | 1125 || (bswap32_p && word_mode == SImode))); |
1123 | 1126 |
1124 if (!bswap32_p && !bswap64_p) | 1127 if (!bswap32_p && !bswap64_p) |
1125 return 0; | 1128 return 0; |
1126 | 1129 |
1261 0, /* todo_flags_start */ | 1264 0, /* todo_flags_start */ |
1262 0 /* todo_flags_finish */ | 1265 0 /* todo_flags_finish */ |
1263 } | 1266 } |
1264 }; | 1267 }; |
1265 | 1268 |
1269 /* Return true if RHS is a suitable operand for a widening multiplication. | |
1270 There are two cases: | |
1271 | |
1272 - RHS makes some value twice as wide. Store that value in *NEW_RHS_OUT | |
1273 if so, and store its type in *TYPE_OUT. | |
1274 | |
1275 - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so, | |
1276 but leave *TYPE_OUT untouched. */ | |
1277 | |
1278 static bool | |
1279 is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out) | |
1280 { | |
1281 gimple stmt; | |
1282 tree type, type1, rhs1; | |
1283 enum tree_code rhs_code; | |
1284 | |
1285 if (TREE_CODE (rhs) == SSA_NAME) | |
1286 { | |
1287 type = TREE_TYPE (rhs); | |
1288 stmt = SSA_NAME_DEF_STMT (rhs); | |
1289 if (!is_gimple_assign (stmt)) | |
1290 return false; | |
1291 | |
1292 rhs_code = gimple_assign_rhs_code (stmt); | |
1293 if (TREE_CODE (type) == INTEGER_TYPE | |
1294 ? !CONVERT_EXPR_CODE_P (rhs_code) | |
1295 : rhs_code != FIXED_CONVERT_EXPR) | |
1296 return false; | |
1297 | |
1298 rhs1 = gimple_assign_rhs1 (stmt); | |
1299 type1 = TREE_TYPE (rhs1); | |
1300 if (TREE_CODE (type1) != TREE_CODE (type) | |
1301 || TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) | |
1302 return false; | |
1303 | |
1304 *new_rhs_out = rhs1; | |
1305 *type_out = type1; | |
1306 return true; | |
1307 } | |
1308 | |
1309 if (TREE_CODE (rhs) == INTEGER_CST) | |
1310 { | |
1311 *new_rhs_out = rhs; | |
1312 *type_out = NULL; | |
1313 return true; | |
1314 } | |
1315 | |
1316 return false; | |
1317 } | |
1318 | |
1319 /* Return true if STMT performs a widening multiplication. If so, | |
1320 store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT | |
1321 respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting | |
1322 those operands to types *TYPE1_OUT and *TYPE2_OUT would give the | |
1323 operands of the multiplication. */ | |
1324 | |
1325 static bool | |
1326 is_widening_mult_p (gimple stmt, | |
1327 tree *type1_out, tree *rhs1_out, | |
1328 tree *type2_out, tree *rhs2_out) | |
1329 { | |
1330 tree type; | |
1331 | |
1332 type = TREE_TYPE (gimple_assign_lhs (stmt)); | |
1333 if (TREE_CODE (type) != INTEGER_TYPE | |
1334 && TREE_CODE (type) != FIXED_POINT_TYPE) | |
1335 return false; | |
1336 | |
1337 if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out)) | |
1338 return false; | |
1339 | |
1340 if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out)) | |
1341 return false; | |
1342 | |
1343 if (*type1_out == NULL) | |
1344 { | |
1345 if (*type2_out == NULL || !int_fits_type_p (*rhs1_out, *type2_out)) | |
1346 return false; | |
1347 *type1_out = *type2_out; | |
1348 } | |
1349 | |
1350 if (*type2_out == NULL) | |
1351 { | |
1352 if (!int_fits_type_p (*rhs2_out, *type1_out)) | |
1353 return false; | |
1354 *type2_out = *type1_out; | |
1355 } | |
1356 | |
1357 return true; | |
1358 } | |
1359 | |
1360 /* Process a single gimple statement STMT, which has a MULT_EXPR as | |
1361 its rhs, and try to convert it into a WIDEN_MULT_EXPR. The return | |
1362 value is true iff we converted the statement. */ | |
1363 | |
1364 static bool | |
1365 convert_mult_to_widen (gimple stmt) | |
1366 { | |
1367 tree lhs, rhs1, rhs2, type, type1, type2; | |
1368 enum insn_code handler; | |
1369 | |
1370 lhs = gimple_assign_lhs (stmt); | |
1371 type = TREE_TYPE (lhs); | |
1372 if (TREE_CODE (type) != INTEGER_TYPE) | |
1373 return false; | |
1374 | |
1375 if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2)) | |
1376 return false; | |
1377 | |
1378 if (TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2)) | |
1379 handler = optab_handler (umul_widen_optab, TYPE_MODE (type)); | |
1380 else if (!TYPE_UNSIGNED (type1) && !TYPE_UNSIGNED (type2)) | |
1381 handler = optab_handler (smul_widen_optab, TYPE_MODE (type)); | |
1382 else | |
1383 handler = optab_handler (usmul_widen_optab, TYPE_MODE (type)); | |
1384 | |
1385 if (handler == CODE_FOR_nothing) | |
1386 return false; | |
1387 | |
1388 gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1)); | |
1389 gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2)); | |
1390 gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); | |
1391 update_stmt (stmt); | |
1392 return true; | |
1393 } | |
1394 | |
1395 /* Process a single gimple statement STMT, which is found at the | |
1396 iterator GSI and has a either a PLUS_EXPR or a MINUS_EXPR as its | |
1397 rhs (given by CODE), and try to convert it into a | |
1398 WIDEN_MULT_PLUS_EXPR or a WIDEN_MULT_MINUS_EXPR. The return value | |
1399 is true iff we converted the statement. */ | |
1400 | |
1401 static bool | |
1402 convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, | |
1403 enum tree_code code) | |
1404 { | |
1405 gimple rhs1_stmt = NULL, rhs2_stmt = NULL; | |
1406 tree type, type1, type2; | |
1407 tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs; | |
1408 enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK; | |
1409 optab this_optab; | |
1410 enum tree_code wmult_code; | |
1411 | |
1412 lhs = gimple_assign_lhs (stmt); | |
1413 type = TREE_TYPE (lhs); | |
1414 if (TREE_CODE (type) != INTEGER_TYPE | |
1415 && TREE_CODE (type) != FIXED_POINT_TYPE) | |
1416 return false; | |
1417 | |
1418 if (code == MINUS_EXPR) | |
1419 wmult_code = WIDEN_MULT_MINUS_EXPR; | |
1420 else | |
1421 wmult_code = WIDEN_MULT_PLUS_EXPR; | |
1422 | |
1423 rhs1 = gimple_assign_rhs1 (stmt); | |
1424 rhs2 = gimple_assign_rhs2 (stmt); | |
1425 | |
1426 if (TREE_CODE (rhs1) == SSA_NAME) | |
1427 { | |
1428 rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); | |
1429 if (is_gimple_assign (rhs1_stmt)) | |
1430 rhs1_code = gimple_assign_rhs_code (rhs1_stmt); | |
1431 } | |
1432 else | |
1433 return false; | |
1434 | |
1435 if (TREE_CODE (rhs2) == SSA_NAME) | |
1436 { | |
1437 rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); | |
1438 if (is_gimple_assign (rhs2_stmt)) | |
1439 rhs2_code = gimple_assign_rhs_code (rhs2_stmt); | |
1440 } | |
1441 else | |
1442 return false; | |
1443 | |
1444 if (code == PLUS_EXPR && rhs1_code == MULT_EXPR) | |
1445 { | |
1446 if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, | |
1447 &type2, &mult_rhs2)) | |
1448 return false; | |
1449 add_rhs = rhs2; | |
1450 } | |
1451 else if (rhs2_code == MULT_EXPR) | |
1452 { | |
1453 if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1, | |
1454 &type2, &mult_rhs2)) | |
1455 return false; | |
1456 add_rhs = rhs1; | |
1457 } | |
1458 else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR) | |
1459 { | |
1460 mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt); | |
1461 mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt); | |
1462 type1 = TREE_TYPE (mult_rhs1); | |
1463 type2 = TREE_TYPE (mult_rhs2); | |
1464 add_rhs = rhs2; | |
1465 } | |
1466 else if (rhs2_code == WIDEN_MULT_EXPR) | |
1467 { | |
1468 mult_rhs1 = gimple_assign_rhs1 (rhs2_stmt); | |
1469 mult_rhs2 = gimple_assign_rhs2 (rhs2_stmt); | |
1470 type1 = TREE_TYPE (mult_rhs1); | |
1471 type2 = TREE_TYPE (mult_rhs2); | |
1472 add_rhs = rhs1; | |
1473 } | |
1474 else | |
1475 return false; | |
1476 | |
1477 if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) | |
1478 return false; | |
1479 | |
1480 /* Verify that the machine can perform a widening multiply | |
1481 accumulate in this mode/signedness combination, otherwise | |
1482 this transformation is likely to pessimize code. */ | |
1483 this_optab = optab_for_tree_code (wmult_code, type1, optab_default); | |
1484 if (optab_handler (this_optab, TYPE_MODE (type)) == CODE_FOR_nothing) | |
1485 return false; | |
1486 | |
1487 /* ??? May need some type verification here? */ | |
1488 | |
1489 gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, | |
1490 fold_convert (type1, mult_rhs1), | |
1491 fold_convert (type2, mult_rhs2), | |
1492 add_rhs); | |
1493 update_stmt (gsi_stmt (*gsi)); | |
1494 return true; | |
1495 } | |
1496 | |
1497 /* Combine the multiplication at MUL_STMT with operands MULOP1 and MULOP2 | |
1498 with uses in additions and subtractions to form fused multiply-add | |
1499 operations. Returns true if successful and MUL_STMT should be removed. */ | |
1500 | |
1501 static bool | |
1502 convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2) | |
1503 { | |
1504 tree mul_result = gimple_get_lhs (mul_stmt); | |
1505 tree type = TREE_TYPE (mul_result); | |
1506 gimple use_stmt, neguse_stmt, fma_stmt; | |
1507 use_operand_p use_p; | |
1508 imm_use_iterator imm_iter; | |
1509 | |
1510 if (FLOAT_TYPE_P (type) | |
1511 && flag_fp_contract_mode == FP_CONTRACT_OFF) | |
1512 return false; | |
1513 | |
1514 /* We don't want to do bitfield reduction ops. */ | |
1515 if (INTEGRAL_TYPE_P (type) | |
1516 && (TYPE_PRECISION (type) | |
1517 != GET_MODE_PRECISION (TYPE_MODE (type)))) | |
1518 return false; | |
1519 | |
1520 /* If the target doesn't support it, don't generate it. We assume that | |
1521 if fma isn't available then fms, fnma or fnms are not either. */ | |
1522 if (optab_handler (fma_optab, TYPE_MODE (type)) == CODE_FOR_nothing) | |
1523 return false; | |
1524 | |
1525 /* Make sure that the multiplication statement becomes dead after | |
1526 the transformation, thus that all uses are transformed to FMAs. | |
1527 This means we assume that an FMA operation has the same cost | |
1528 as an addition. */ | |
1529 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, mul_result) | |
1530 { | |
1531 enum tree_code use_code; | |
1532 tree result = mul_result; | |
1533 bool negate_p = false; | |
1534 | |
1535 use_stmt = USE_STMT (use_p); | |
1536 | |
1537 if (is_gimple_debug (use_stmt)) | |
1538 continue; | |
1539 | |
1540 /* For now restrict this operations to single basic blocks. In theory | |
1541 we would want to support sinking the multiplication in | |
1542 m = a*b; | |
1543 if () | |
1544 ma = m + c; | |
1545 else | |
1546 d = m; | |
1547 to form a fma in the then block and sink the multiplication to the | |
1548 else block. */ | |
1549 if (gimple_bb (use_stmt) != gimple_bb (mul_stmt)) | |
1550 return false; | |
1551 | |
1552 if (!is_gimple_assign (use_stmt)) | |
1553 return false; | |
1554 | |
1555 use_code = gimple_assign_rhs_code (use_stmt); | |
1556 | |
1557 /* A negate on the multiplication leads to FNMA. */ | |
1558 if (use_code == NEGATE_EXPR) | |
1559 { | |
1560 ssa_op_iter iter; | |
1561 tree use; | |
1562 | |
1563 result = gimple_assign_lhs (use_stmt); | |
1564 | |
1565 /* Make sure the negate statement becomes dead with this | |
1566 single transformation. */ | |
1567 if (!single_imm_use (gimple_assign_lhs (use_stmt), | |
1568 &use_p, &neguse_stmt)) | |
1569 return false; | |
1570 | |
1571 /* Make sure the multiplication isn't also used on that stmt. */ | |
1572 FOR_EACH_SSA_TREE_OPERAND (use, neguse_stmt, iter, SSA_OP_USE) | |
1573 if (use == mul_result) | |
1574 return false; | |
1575 | |
1576 /* Re-validate. */ | |
1577 use_stmt = neguse_stmt; | |
1578 if (gimple_bb (use_stmt) != gimple_bb (mul_stmt)) | |
1579 return false; | |
1580 if (!is_gimple_assign (use_stmt)) | |
1581 return false; | |
1582 | |
1583 use_code = gimple_assign_rhs_code (use_stmt); | |
1584 negate_p = true; | |
1585 } | |
1586 | |
1587 switch (use_code) | |
1588 { | |
1589 case MINUS_EXPR: | |
1590 if (gimple_assign_rhs2 (use_stmt) == result) | |
1591 negate_p = !negate_p; | |
1592 break; | |
1593 case PLUS_EXPR: | |
1594 break; | |
1595 default: | |
1596 /* FMA can only be formed from PLUS and MINUS. */ | |
1597 return false; | |
1598 } | |
1599 | |
1600 /* We can't handle a * b + a * b. */ | |
1601 if (gimple_assign_rhs1 (use_stmt) == gimple_assign_rhs2 (use_stmt)) | |
1602 return false; | |
1603 | |
1604 /* While it is possible to validate whether or not the exact form | |
1605 that we've recognized is available in the backend, the assumption | |
1606 is that the transformation is never a loss. For instance, suppose | |
1607 the target only has the plain FMA pattern available. Consider | |
1608 a*b-c -> fma(a,b,-c): we've exchanged MUL+SUB for FMA+NEG, which | |
1609 is still two operations. Consider -(a*b)-c -> fma(-a,b,-c): we | |
1610 still have 3 operations, but in the FMA form the two NEGs are | |
1611 independant and could be run in parallel. */ | |
1612 } | |
1613 | |
1614 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, mul_result) | |
1615 { | |
1616 gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); | |
1617 enum tree_code use_code; | |
1618 tree addop, mulop1 = op1, result = mul_result; | |
1619 bool negate_p = false; | |
1620 | |
1621 if (is_gimple_debug (use_stmt)) | |
1622 continue; | |
1623 | |
1624 use_code = gimple_assign_rhs_code (use_stmt); | |
1625 if (use_code == NEGATE_EXPR) | |
1626 { | |
1627 result = gimple_assign_lhs (use_stmt); | |
1628 single_imm_use (gimple_assign_lhs (use_stmt), &use_p, &neguse_stmt); | |
1629 gsi_remove (&gsi, true); | |
1630 release_defs (use_stmt); | |
1631 | |
1632 use_stmt = neguse_stmt; | |
1633 gsi = gsi_for_stmt (use_stmt); | |
1634 use_code = gimple_assign_rhs_code (use_stmt); | |
1635 negate_p = true; | |
1636 } | |
1637 | |
1638 if (gimple_assign_rhs1 (use_stmt) == result) | |
1639 { | |
1640 addop = gimple_assign_rhs2 (use_stmt); | |
1641 /* a * b - c -> a * b + (-c) */ | |
1642 if (gimple_assign_rhs_code (use_stmt) == MINUS_EXPR) | |
1643 addop = force_gimple_operand_gsi (&gsi, | |
1644 build1 (NEGATE_EXPR, | |
1645 type, addop), | |
1646 true, NULL_TREE, true, | |
1647 GSI_SAME_STMT); | |
1648 } | |
1649 else | |
1650 { | |
1651 addop = gimple_assign_rhs1 (use_stmt); | |
1652 /* a - b * c -> (-b) * c + a */ | |
1653 if (gimple_assign_rhs_code (use_stmt) == MINUS_EXPR) | |
1654 negate_p = !negate_p; | |
1655 } | |
1656 | |
1657 if (negate_p) | |
1658 mulop1 = force_gimple_operand_gsi (&gsi, | |
1659 build1 (NEGATE_EXPR, | |
1660 type, mulop1), | |
1661 true, NULL_TREE, true, | |
1662 GSI_SAME_STMT); | |
1663 | |
1664 fma_stmt = gimple_build_assign_with_ops3 (FMA_EXPR, | |
1665 gimple_assign_lhs (use_stmt), | |
1666 mulop1, op2, | |
1667 addop); | |
1668 gsi_replace (&gsi, fma_stmt, true); | |
1669 } | |
1670 | |
1671 return true; | |
1672 } | |
1673 | |
1266 /* Find integer multiplications where the operands are extended from | 1674 /* Find integer multiplications where the operands are extended from |
1267 smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR | 1675 smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR |
1268 where appropriate. */ | 1676 where appropriate. */ |
1269 | 1677 |
1270 static unsigned int | 1678 static unsigned int |
1271 execute_optimize_widening_mul (void) | 1679 execute_optimize_widening_mul (void) |
1272 { | 1680 { |
1273 bool changed = false; | |
1274 basic_block bb; | 1681 basic_block bb; |
1682 bool cfg_changed = false; | |
1275 | 1683 |
1276 FOR_EACH_BB (bb) | 1684 FOR_EACH_BB (bb) |
1277 { | 1685 { |
1278 gimple_stmt_iterator gsi; | 1686 gimple_stmt_iterator gsi; |
1279 | 1687 |
1280 for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 1688 for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);) |
1281 { | 1689 { |
1282 gimple stmt = gsi_stmt (gsi); | 1690 gimple stmt = gsi_stmt (gsi); |
1283 gimple rhs1_stmt = NULL, rhs2_stmt = NULL; | 1691 enum tree_code code; |
1284 tree type, type1 = NULL, type2 = NULL; | 1692 |
1285 tree rhs1, rhs2, rhs1_convop = NULL, rhs2_convop = NULL; | 1693 if (is_gimple_assign (stmt)) |
1286 enum tree_code rhs1_code, rhs2_code; | |
1287 | |
1288 if (!is_gimple_assign (stmt) | |
1289 || gimple_assign_rhs_code (stmt) != MULT_EXPR) | |
1290 continue; | |
1291 | |
1292 type = TREE_TYPE (gimple_assign_lhs (stmt)); | |
1293 | |
1294 if (TREE_CODE (type) != INTEGER_TYPE) | |
1295 continue; | |
1296 | |
1297 rhs1 = gimple_assign_rhs1 (stmt); | |
1298 rhs2 = gimple_assign_rhs2 (stmt); | |
1299 | |
1300 if (TREE_CODE (rhs1) == SSA_NAME) | |
1301 { | 1694 { |
1302 rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); | 1695 code = gimple_assign_rhs_code (stmt); |
1303 if (!is_gimple_assign (rhs1_stmt)) | 1696 switch (code) |
1304 continue; | 1697 { |
1305 rhs1_code = gimple_assign_rhs_code (rhs1_stmt); | 1698 case MULT_EXPR: |
1306 if (!CONVERT_EXPR_CODE_P (rhs1_code)) | 1699 if (!convert_mult_to_widen (stmt) |
1307 continue; | 1700 && convert_mult_to_fma (stmt, |
1308 rhs1_convop = gimple_assign_rhs1 (rhs1_stmt); | 1701 gimple_assign_rhs1 (stmt), |
1309 type1 = TREE_TYPE (rhs1_convop); | 1702 gimple_assign_rhs2 (stmt))) |
1310 if (TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) | 1703 { |
1311 continue; | 1704 gsi_remove (&gsi, true); |
1705 release_defs (stmt); | |
1706 continue; | |
1707 } | |
1708 break; | |
1709 | |
1710 case PLUS_EXPR: | |
1711 case MINUS_EXPR: | |
1712 convert_plusminus_to_widen (&gsi, stmt, code); | |
1713 break; | |
1714 | |
1715 default:; | |
1716 } | |
1312 } | 1717 } |
1313 else if (TREE_CODE (rhs1) != INTEGER_CST) | 1718 else if (is_gimple_call (stmt) |
1314 continue; | 1719 && gimple_call_lhs (stmt)) |
1315 | |
1316 if (TREE_CODE (rhs2) == SSA_NAME) | |
1317 { | 1720 { |
1318 rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); | 1721 tree fndecl = gimple_call_fndecl (stmt); |
1319 if (!is_gimple_assign (rhs2_stmt)) | 1722 if (fndecl |
1320 continue; | 1723 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) |
1321 rhs2_code = gimple_assign_rhs_code (rhs2_stmt); | 1724 { |
1322 if (!CONVERT_EXPR_CODE_P (rhs2_code)) | 1725 switch (DECL_FUNCTION_CODE (fndecl)) |
1323 continue; | 1726 { |
1324 rhs2_convop = gimple_assign_rhs1 (rhs2_stmt); | 1727 case BUILT_IN_POWF: |
1325 type2 = TREE_TYPE (rhs2_convop); | 1728 case BUILT_IN_POW: |
1326 if (TYPE_PRECISION (type2) * 2 != TYPE_PRECISION (type)) | 1729 case BUILT_IN_POWL: |
1327 continue; | 1730 if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST |
1731 && REAL_VALUES_EQUAL | |
1732 (TREE_REAL_CST (gimple_call_arg (stmt, 1)), | |
1733 dconst2) | |
1734 && convert_mult_to_fma (stmt, | |
1735 gimple_call_arg (stmt, 0), | |
1736 gimple_call_arg (stmt, 0))) | |
1737 { | |
1738 unlink_stmt_vdef (stmt); | |
1739 gsi_remove (&gsi, true); | |
1740 release_defs (stmt); | |
1741 if (gimple_purge_dead_eh_edges (bb)) | |
1742 cfg_changed = true; | |
1743 continue; | |
1744 } | |
1745 break; | |
1746 | |
1747 default:; | |
1748 } | |
1749 } | |
1328 } | 1750 } |
1329 else if (TREE_CODE (rhs2) != INTEGER_CST) | 1751 gsi_next (&gsi); |
1330 continue; | 1752 } |
1331 | 1753 } |
1332 if (rhs1_stmt == NULL && rhs2_stmt == NULL) | 1754 |
1333 continue; | 1755 return cfg_changed ? TODO_cleanup_cfg : 0; |
1334 | |
1335 /* Verify that the machine can perform a widening multiply in this | |
1336 mode/signedness combination, otherwise this transformation is | |
1337 likely to pessimize code. */ | |
1338 if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1)) | |
1339 && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2)) | |
1340 && (optab_handler (umul_widen_optab, TYPE_MODE (type)) | |
1341 ->insn_code == CODE_FOR_nothing)) | |
1342 continue; | |
1343 else if ((rhs1_stmt == NULL || !TYPE_UNSIGNED (type1)) | |
1344 && (rhs2_stmt == NULL || !TYPE_UNSIGNED (type2)) | |
1345 && (optab_handler (smul_widen_optab, TYPE_MODE (type)) | |
1346 ->insn_code == CODE_FOR_nothing)) | |
1347 continue; | |
1348 else if (rhs1_stmt != NULL && rhs2_stmt != 0 | |
1349 && (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) | |
1350 && (optab_handler (usmul_widen_optab, TYPE_MODE (type)) | |
1351 ->insn_code == CODE_FOR_nothing)) | |
1352 continue; | |
1353 | |
1354 if ((rhs1_stmt == NULL && !int_fits_type_p (rhs1, type2)) | |
1355 || (rhs2_stmt == NULL && !int_fits_type_p (rhs2, type1))) | |
1356 continue; | |
1357 | |
1358 if (rhs1_stmt == NULL) | |
1359 gimple_assign_set_rhs1 (stmt, fold_convert (type2, rhs1)); | |
1360 else | |
1361 gimple_assign_set_rhs1 (stmt, rhs1_convop); | |
1362 if (rhs2_stmt == NULL) | |
1363 gimple_assign_set_rhs2 (stmt, fold_convert (type1, rhs2)); | |
1364 else | |
1365 gimple_assign_set_rhs2 (stmt, rhs2_convop); | |
1366 gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); | |
1367 update_stmt (stmt); | |
1368 changed = true; | |
1369 } | |
1370 } | |
1371 return (changed ? TODO_dump_func | TODO_update_ssa | TODO_verify_ssa | |
1372 | TODO_verify_stmts : 0); | |
1373 } | 1756 } |
1374 | 1757 |
1375 static bool | 1758 static bool |
1376 gate_optimize_widening_mul (void) | 1759 gate_optimize_widening_mul (void) |
1377 { | 1760 { |
1391 TV_NONE, /* tv_id */ | 1774 TV_NONE, /* tv_id */ |
1392 PROP_ssa, /* properties_required */ | 1775 PROP_ssa, /* properties_required */ |
1393 0, /* properties_provided */ | 1776 0, /* properties_provided */ |
1394 0, /* properties_destroyed */ | 1777 0, /* properties_destroyed */ |
1395 0, /* todo_flags_start */ | 1778 0, /* todo_flags_start */ |
1396 0 /* todo_flags_finish */ | 1779 TODO_verify_ssa |
1780 | TODO_verify_stmts | |
1781 | TODO_dump_func | |
1782 | TODO_update_ssa /* todo_flags_finish */ | |
1397 } | 1783 } |
1398 }; | 1784 }; |