void if_conversion::convert_kill_instructions(region_node *r, value *em, bool branch, container_node *c) { value *cnd = NULL; for (node_iterator I = c->begin(), E = c->end(), N; I != E; I = N) { N = I + 1; if (!I->is_alu_inst()) continue; alu_node *a = static_cast<alu_node*>(*I); unsigned flags = a->bc.op_ptr->flags; if (!(flags & AF_KILL)) continue; // ignore predicated or non-const kill instructions if (a->pred || !a->src[0]->is_const() || !a->src[1]->is_const()) continue; literal l0 = a->src[0]->literal_value; literal l1 = a->src[1]->literal_value; expr_handler::apply_alu_src_mod(a->bc, 0, l0); expr_handler::apply_alu_src_mod(a->bc, 1, l1); if (expr_handler::evaluate_condition(flags, l0, l1)) { // kill with constant 'true' condition, we'll convert it to the // conditional kill outside of the if-then-else block a->remove(); if (!cnd) { cnd = get_select_value_for_em(sh, em); } else { // more than one kill with the same condition, just remove it continue; } r->insert_before(a); a->bc.set_op(branch ? ALU_OP2_KILLE_INT : ALU_OP2_KILLNE_INT); a->src[0] = cnd; a->src[1] = sh.get_const_value(0); // clear modifiers memset(&a->bc.src[0], 0, sizeof(bc_alu_src)); memset(&a->bc.src[1], 0, sizeof(bc_alu_src)); } else { // kill with constant 'false' condition, this shouldn't happen // but remove it anyway a->remove(); } } }
unsigned if_conversion::try_convert_kills(region_node* r) { // handling the simplest (and probably most frequent) case only - // if - 4 kills - endif // TODO handle more complex cases depart_node *d1 = static_cast<depart_node*>(r->front()); if (!d1->is_depart()) return 0; if_node *f = static_cast<if_node*>(d1->front()); if (!f->is_if()) return 0; depart_node *d2 = static_cast<depart_node*>(f->front()); if (!d2->is_depart()) return 0; unsigned cnt = 0; for (node_iterator I = d2->begin(), E = d2->end(); I != E; ++I) { alu_node *n = static_cast<alu_node*>(*I); if (!n->is_alu_inst()) return 0; if (!(n->bc.op_ptr->flags & AF_KILL)) return 0; if (n->bc.op_ptr->src_count != 2 || n->src.size() != 2) return 0; value *s1 = n->src[0], *s2 = n->src[1]; // assuming that the KILL with constant operands is "always kill" if (!s1 || !s2 || !s1->is_const() || !s2->is_const()) return 0; ++cnt; } if (cnt > 4) return 0; value *cond = f->cond; value *pred = get_select_value_for_em(sh, cond); if (!pred) return 0; for (node_iterator N, I = d2->begin(), E = d2->end(); I != E; I = N) { N = I; ++N; alu_node *n = static_cast<alu_node*>(*I); IFC_DUMP( cerr << "converting "; dump::dump_op(n); cerr << " " << n << "\n"; ); n->remove(); n->bc.set_op(ALU_OP2_KILLE_INT); n->src[0] = pred; n->src[1] = sh.get_const_value(0); // reset src modifiers memset(&n->bc.src[0], 0, sizeof(bc_alu_src)); memset(&n->bc.src[1], 0, sizeof(bc_alu_src)); r->insert_before(n); }