+ switch (get_irn_opcode(irn)) {
+ case iro_Const:
+ case iro_SymConst:
+ return 1;
+ case iro_Add:
+ op = get_irn_op(get_Add_left(irn));
+ if (op != op_Const && op != op_SymConst)
+ return 0;
+ op = get_irn_op(get_Add_right(irn));
+ if (op != op_Const && op != op_SymConst)
+ return 0;
+ return 1;
+ default:
+ return 0;
+ }
+} /* is_constant_expr */
+
+/**
+ * Apply distributive Law for Mul and Add/Sub
+ */
+static int reverse_rule_distributive(ir_node **node) {
+ ir_node *n = *node;
+ ir_node *left = get_binop_left(n);
+ ir_node *right = get_binop_right(n);
+ ir_node *x, *blk, *curr_blk;
+ ir_node *a, *b, *irn;
+ ir_op *op;
+ ir_mode *mode;
+ dbg_info *dbg;
+
+ op = get_irn_op(left);
+ if (op != get_irn_op(right))
+ return 0;
+
+ if (op == op_Shl) {
+ x = get_Shl_right(left);
+
+ if (x == get_Shl_right(right)) {
+ /* (a << x) +/- (b << x) ==> (a +/- b) << x */
+ a = get_Shl_left(left);
+ b = get_Shl_left(right);
+ goto transform;
+ }
+ } else if (op == op_Mul) {
+ x = get_Mul_left(left);
+
+ if (x == get_Mul_left(right)) {
+ /* (x * a) +/- (x * b) ==> (a +/- b) * x */
+ a = get_Mul_right(left);
+ b = get_Mul_right(right);
+ goto transform;
+ } else if (x == get_Mul_right(right)) {
+ /* (x * a) +/- (b * x) ==> (a +/- b) * x */
+ a = get_Mul_right(left);
+ b = get_Mul_left(right);
+ goto transform;
+ }
+
+ x = get_Mul_right(left);
+
+ if (x == get_Mul_right(right)) {
+ /* (a * x) +/- (b * x) ==> (a +/- b) * x */
+ a = get_Mul_left(left);
+ b = get_Mul_left(right);
+ goto transform;
+ } else if (x == get_Mul_left(right)) {
+ /* (a * x) +/- (x * b) ==> (a +/- b) * x */
+ a = get_Mul_left(left);
+ b = get_Mul_right(right);
+ goto transform;
+ }
+ }
+ return 0;
+
+transform:
+ curr_blk = get_nodes_block(n);
+
+ blk = earliest_block(a, b, curr_blk);
+
+ dbg = get_irn_dbg_info(n);
+ mode = get_irn_mode(n);
+
+ if (is_Add(n))
+ irn = new_rd_Add(dbg, current_ir_graph, blk, a, b, mode);
+ else
+ irn = new_rd_Sub(dbg, current_ir_graph, blk, a, b, mode);
+
+ blk = earliest_block(irn, x, curr_blk);
+
+ if (op == op_Mul)
+ irn = new_rd_Mul(dbg, current_ir_graph, blk, irn, x, mode);
+ else
+ irn = new_rd_Shl(dbg, current_ir_graph, blk, irn, x, mode);
+
+ exchange(n, irn);
+ *node = irn;
+ return 1;
+} /* reverse_rule_distributive */