+ pred = new_r_Conv(block, pred, mode);
+ set_Add_left(irn, pred);
+ }
+ pred = get_Add_right(irn);
+ if (get_irn_mode(pred) != mode) {
+ ir_node *block = get_nodes_block(pred);
+
+ pred = new_r_Conv(block, pred, mode);
+ set_Add_right(irn, pred);
+ }
+ }
+ } else if (is_Sub(irn)) {
+ ir_mode *mode = get_irn_mode(irn);
+
+ if (mode_is_int(mode)) {
+ ir_node *left = get_Sub_left(irn);
+ ir_node *right = get_Sub_right(irn);
+ ir_mode *l_mode = get_irn_mode(left);
+ ir_mode *r_mode = get_irn_mode(right);
+
+ if (mode_is_int(l_mode) && mode_is_int(r_mode)) {
+ if (l_mode != mode) {
+ ir_node *block = get_nodes_block(left);
+
+ left = new_r_Conv(block, left, mode);
+ set_Sub_left(irn, left);
+ }
+ if (r_mode != mode) {
+ ir_node *block = get_nodes_block(right);
+
+ right = new_r_Conv(block, right, mode);
+ set_Sub_right(irn, right);
+ }
+ }
+ } else if (mode_is_reference(mode)) {
+ ir_node *left = get_Sub_left(irn);
+ ir_node *right = get_Sub_right(irn);
+ ir_mode *l_mode = get_irn_mode(left);
+ ir_mode *r_mode = get_irn_mode(right);
+ if (mode_is_int(l_mode)) {
+ /* Usually, Sub(I*,P) is an error, hence the verifier rejects it.
+ * However, it is correct in this case, so add Conv to make verifier happy. */
+ ir_node *block = get_nodes_block(right);
+ ir_node *lconv = new_r_Conv(block, left, r_mode);
+ assert(mode_is_reference(r_mode));
+ set_Sub_left(irn, lconv);
+ }
+ }
+ }
+} /* fix_adds_and_subs */
+
+/* Performs Operator Strength Reduction for the passed graph. */
+void opt_osr(ir_graph *irg, unsigned flags)
+{
+ iv_env env;
+ int edges;
+
+ FIRM_DBG_REGISTER(dbg, "firm.opt.osr");
+
+ DB((dbg, LEVEL_1, "Doing Operator Strength Reduction for %+F\n", irg));