+/**
+ * Reduce a node.
+ *
+ * @param *itervar_phi The iteration variable of a loop.
+ * @param *env Free environment pointer.
+ */
+static void reduce_itervar(ir_node *itervar_phi, void *env)
+{
+ induct_var_info ivi;
+
+ if (get_irn_op(itervar_phi) != op_Phi)
+ return;
+
+ ivi.itervar_phi = itervar_phi;
+
+ /* This "if" finds the iteration variable. */
+ if (is_induction_variable(&ivi)) {
+ int i, op_out;
+
+ for (i = 0; i < ivi.phi_pred; i++) {
+ ir_node *out = get_irn_out(ivi.itervar_phi, i);
+ ir_op *out_op = get_irn_op(out);
+ if(ivi.reducible){
+ if(ivi.phi_pred == 3 && out != ivi.op && out !=ivi.cmp){
+ ir_node *reduced = reducible(out, &ivi);
+ if (reduced != NULL)
+ exchange( reduced, ivi.itervar_phi);
+ }
+ } else if (out_op == op_Mul)
+ if(reduce(out, &ivi) && ivi.reducible){
+ ir_node *reduced = reducible(ivi.reducible_node, &ivi);
+ if(reduced != NULL)
+ exchange(reduced, ivi.new_phi);
+ ivi.reducible = 0;
+ set_Phi_pred(ivi.new_phi, ivi.init_pred_pos, ivi.new_init);
+ set_irn_mode(ivi.new_phi,get_irn_mode(ivi.new_init));
+ set_irn_mode(ivi.new_op,get_irn_mode(ivi.new_phi));
+ }
+ }
+
+ op_out = get_irn_n_outs(ivi.op);
+ for (i = 0; i < op_out; i++){
+ ir_node *out = get_irn_out(ivi.op, i);
+ ir_op *out_op = get_irn_op(out);
+ if(op_out == 2 && out != ivi.itervar_phi){
+ ir_node *reduced = reducible(out, &ivi);
+ if(reduced != NULL)
+ exchange( reduced, ivi.op);
+ }else if (out_op == op_Mul)
+ if(reduce(out, &ivi) && ivi.reducible){
+ ir_node *reduced = reducible(ivi.reducible_node, &ivi);
+ if(reduced != NULL)
+ exchange(reduced, ivi.new_phi);
+ ivi.reducible = 0;
+ set_Phi_pred(ivi.new_phi, ivi.init_pred_pos, ivi.new_init);
+ set_irn_mode(ivi.new_phi,get_irn_mode(ivi.new_init));
+ set_irn_mode(ivi.new_op,get_irn_mode(ivi.new_phi));
+ }
+ }
+
+ if(ivi.reducible){
+ if(get_irn_op(ivi.op) == op_Add)
+ if(get_Add_left(ivi.op) == ivi.itervar_phi)
+ set_Add_right(ivi.op, ivi.increment);
+ else
+ set_Add_left(ivi.op, ivi.increment);
+ else if(get_Sub_left(ivi.op) == ivi.itervar_phi)
+ set_Sub_right(ivi.op, ivi.increment);
+ else
+ set_Sub_right(ivi.op, ivi.increment);
+ set_Phi_pred(ivi.itervar_phi, ivi.init_pred_pos, ivi.init);
+ set_irn_mode(ivi.itervar_phi, get_irn_mode(ivi.init));
+ set_irn_mode(ivi.op, get_irn_mode(ivi.itervar_phi));
+ if (ivi.cmp != NULL){
+ set_irn_mode(ivi.cmp_const, get_irn_mode(ivi.itervar_phi));
+ if(get_Cmp_left(ivi.cmp) == ivi.itervar_phi)
+ set_Cmp_right(ivi.cmp, ivi.cmp_const);
+ else
+ set_Cmp_left(ivi.cmp, ivi.cmp_const);
+ }
+ }
+ }
+}