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 };