-static ir_node *transform_node_Add(ir_node *n)
-{
- ir_mode *mode;
- ir_node *oldn = n;
-
- n = transform_node_AddSub(n);
-
- mode = get_irn_mode(n);
- if (mode_is_num(mode)) {
- ir_node *a = get_Add_left(n);
-
- if (a == get_Add_right(n)) {
- ir_node *block = get_nodes_block(n);
-
- n = new_rd_Mul(
- get_irn_dbg_info(n),
- current_ir_graph,
- block,
- a,
- new_r_Const_long(current_ir_graph, block, mode, 2),
- mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_A);
- }
- else {
- ir_node *b = get_Add_right(n);
-
- if (get_irn_op(a) == op_Minus) {
- n = new_rd_Sub(
- get_irn_dbg_info(n),
- current_ir_graph,
- get_nodes_block(n),
- b,
- get_Minus_op(a),
- mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
- }
- else if (get_irn_op(b) == op_Minus) {
- n = new_rd_Sub(
- get_irn_dbg_info(n),
- current_ir_graph,
- get_nodes_block(n),
- a,
- get_Minus_op(b),
- mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
- }
- }
- }
- return n;
-}
-
-/**
- * Do the AddSub optimization, then Transform Sub(0,a) into Minus(a).
- */
-static ir_node *transform_node_Sub(ir_node *n)
-{
- ir_mode *mode;
- ir_node *oldn = n;
-
- n = transform_node_AddSub(n);
-
- mode = get_irn_mode(n);
- if (mode_is_num(mode) && (classify_Const(get_Sub_left(n)) == CNST_NULL)) {
- n = new_rd_Minus(
- get_irn_dbg_info(n),
- current_ir_graph,
- get_nodes_block(n),
- get_Sub_right(n),
- mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_0_A);
- }
-
- return n;
-}
+static ir_node *transform_node_Add(ir_node *n) {
+ ir_mode *mode;
+ ir_node *a, *b, *c, *oldn = n;
+
+ n = transform_node_AddSub(n);
+
+ a = get_Add_left(n);
+ b = get_Add_right(n);
+
+ HANDLE_BINOP_PHI(tarval_add, a,b,c);
+
+ mode = get_irn_mode(n);
+
+ /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
+ if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic))
+ return n;
+
+ if (mode_is_num(mode)) {
+ if (a == b) {
+ ir_node *block = get_irn_n(n, -1);
+
+ n = new_rd_Mul(
+ get_irn_dbg_info(n),
+ current_ir_graph,
+ block,
+ a,
+ new_r_Const_long(current_ir_graph, block, mode, 2),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_A);
+ } else if (get_irn_op(a) == op_Minus) {
+ n = new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph,
+ get_irn_n(n, -1),
+ b,
+ get_Minus_op(a),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
+ } else if (get_irn_op(b) == op_Minus) {
+ n = new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph,
+ get_irn_n(n, -1),
+ a,
+ get_Minus_op(b),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
+ }
+ /* do NOT execute this code if reassociation is enabled, it does the inverse! */
+ else if (!get_opt_reassociation() && get_irn_op(a) == op_Mul) {
+ ir_node *ma = get_Mul_left(a);
+ ir_node *mb = get_Mul_right(a);
+
+ if (b == ma) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
+ } else if (b == mb) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
+ }
+ }
+ /* do NOT execute this code if reassociation is enabled, it does the inverse! */
+ else if (!get_opt_reassociation() && get_irn_op(b) == op_Mul) {
+ ir_node *ma = get_Mul_left(b);
+ ir_node *mb = get_Mul_right(b);
+
+ if (a == ma) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
+ } else if (a == mb) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
+ }
+ }
+ }
+ return n;
+} /* transform_node_Add */
+
+/**
+ * Do the AddSub optimization, then Transform
+ * Constant folding on Phi
+ * Sub(0,a) -> Minus(a)
+ * Sub(Mul(a, x), a) -> Mul(a, x-1)
+ * Sub(Sub(x, y), b) -> Sub(x, Add(y,b))
+ */
+static ir_node *transform_node_Sub(ir_node *n) {
+ ir_mode *mode;
+ ir_node *oldn = n;
+ ir_node *a, *b, *c;
+
+ n = transform_node_AddSub(n);
+
+ a = get_Sub_left(n);
+ b = get_Sub_right(n);
+
+ HANDLE_BINOP_PHI(tarval_sub, a,b,c);
+
+ mode = get_irn_mode(n);
+
+ /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
+ if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic))
+ return n;
+
+ /* Beware of Sub(P, P) which cannot be optimized into a simple Minus ... */
+ if (mode_is_num(mode) && mode == get_irn_mode(a) && (classify_Const(a) == CNST_NULL)) {
+ n = new_rd_Minus(
+ get_irn_dbg_info(n),
+ current_ir_graph,
+ get_irn_n(n, -1),
+ b,
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_0_A);
+ }
+ /* do NOT execute this code if reassociation is enabled, it does the inverse! */
+ else if (get_opt_reassociation() && get_irn_op(a) == op_Mul) {
+ ir_node *ma = get_Mul_left(a);
+ ir_node *mb = get_Mul_right(a);
+
+ if (ma == b) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ ma,
+ new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ mb,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MUL_A_X_A);
+ } else if (mb == b) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ mb,
+ new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ ma,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MUL_A_X_A);
+ }
+ } else if (get_irn_op(a) == op_Sub) {
+ ir_node *x = get_Sub_left(a);
+ ir_node *y = get_Sub_right(a);
+ ir_node *blk = get_irn_n(n, -1);
+ ir_mode *m_b = get_irn_mode(b);
+ ir_mode *m_y = get_irn_mode(y);
+ ir_node *add;
+
+ /* Determine the right mode for the Add. */
+ if (m_b == m_y)
+ mode = m_b;
+ else if (mode_is_reference(m_b))
+ mode = m_b;
+ else if (mode_is_reference(m_y))
+ mode = m_y;
+ else {
+ /*
+ * Both modes are different but none is reference,
+ * happens for instance in SubP(SubP(P, Iu), Is).
+ * We have two possibilities here: Cast or ignore.
+ * Currently we ignore this case.
+ */
+ return n;
+ }
+
+ add = new_r_Add(current_ir_graph, blk, y, b, mode);
+
+ set_Sub_left(n, x);
+ set_Sub_right(n, add);
+ DBG_OPT_ALGSIM0(n, n, FS_OPT_SUB_SUB_X_Y_Z);
+ }
+
+ return n;
+} /* transform_node_Sub */