static int worst_cost (const struct predicate *p) { if (p) { unsigned int cost_r, cost_l, worst; cost_l = worst_cost (p->pred_left); cost_r = worst_cost (p->pred_right); worst = (cost_l > cost_r) ? cost_l : cost_r; if (worst < p->p_cost) worst = p->p_cost; return worst; } else { return 0; } }
MyAlgorithm::MyAlgorithm(const Problem& pbm, const SetUpParams& setup): _pbm(pbm), _setup(setup) { initialize(); evaluate(); _upper_cost = best_cost(); _lower_cost = worst_cost(); mixrate = 1; }
/* Consider swapping p->pred_left->pred_right with p->pred_right, * if that yields a faster evaluation. Normally the left predicate is * evaluated first. * * If the operation is an OR, we want the left predicate to be the one that * succeeds most often. If it is an AND, we want it to be the predicate that * fails most often. * * We don't consider swapping arms of an operator where their cost is * different or where they have side effects. * * A viable test case for this is * ./find -D opt -O3 . \! -type f -o -type d * Here, the ! -type f should be evaluated first, * as we assume that 95% of inodes are vanilla files. */ static bool consider_arm_swap (struct predicate *p) { int left_cost, right_cost; const char *reason = NULL; struct predicate **pl, **pr; if (BI_OP != p->p_type) reason = "Not a binary operation"; if (!reason) { if (NULL == p->pred_left || NULL == p->pred_right) reason = "Doesn't have two arms"; } if (!reason) { if (NULL == p->pred_left->pred_right) reason = "Left arm has no child on RHS"; } pr = &p->pred_right; pl = &p->pred_left->pred_right; if (!reason) { if (subtree_has_side_effects (*pl)) reason = "Left subtree has side-effects"; } if (!reason) { if (subtree_has_side_effects (*pr)) reason = "Right subtree has side-effects"; } if (!reason) { left_cost = worst_cost (*pl); right_cost = worst_cost (*pr); if (left_cost < right_cost) { reason = "efficient as-is"; } } if (!reason) { bool want_swap; if (left_cost == right_cost) { /* it's a candidate */ float succ_rate_l = (*pl)->est_success_rate; float succ_rate_r = (*pr)->est_success_rate; if (options.debug_options & DebugTreeOpt) { fprintf (stderr, "Success rates: l=%f, r=%f\n", succ_rate_l, succ_rate_r); } if (pred_is (p, pred_or)) { want_swap = succ_rate_r < succ_rate_l; if (!want_swap) reason = "Operation is OR; right success rate >= left"; } else if (pred_is (p, pred_and)) { want_swap = succ_rate_r > succ_rate_l; if (!want_swap) reason = "Operation is AND; right success rate <= left"; } else { want_swap = false; reason = "Not 'AND' or 'OR'"; } } else { want_swap = true; } if (want_swap) { if (options.debug_options & DebugTreeOpt) { fprintf (stderr, "Performing arm swap on:\n"); print_tree (stderr, p, 0); } perform_arm_swap (p); return true; } } if (options.debug_options & DebugTreeOpt) { fprintf (stderr, "Not an arm swap candidate (%s):\n", reason); print_tree (stderr, p, 0); } return false; }