Пример #1
0
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();
		}
	}
}
Пример #2
0
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);
	}