src/lima/gp_ir/if_conversion.c
//Rewrites phi nodes in the exit block to use selects instead
//cond_reg must be true if pred1 was taken, false if pred2 was taken
Rewrites phi nodes in the exit block to use selects instead
cond_reg must be true if pred1 was taken, false if pred2 was taken
Rewrites phi nodes in the exit block to use selects instead cond_reg must be true if pred1 was taken false if pred2 was taken
static bool rewrite_phi_nodes(lima_gp_ir_block_t* exit,
							  lima_gp_ir_reg_t* cond_reg,
							  lima_gp_ir_block_t* pred1,
							  lima_gp_ir_block_t* pred2)
{
	unsigned i;
	lima_gp_ir_load_reg_node_t* cond = lima_gp_ir_load_reg_node_create();
	if (!cond)
		return false;
	cond->reg = cond_reg;
	cond->component = 0;
	lima_gp_ir_phi_node_t* phi_node;
	ptrset_iter_t iter = ptrset_iter_create(exit->phi_nodes);
	ptrset_iter_for_each(iter, phi_node)
	{
		lima_gp_ir_reg_t* pred1_reg, *pred2_reg;
		assert(phi_node->num_sources == 2);
		if (phi_node->sources[0].pred == pred1)
		{
			pred1_reg = phi_node->sources[0].reg;
			pred2_reg = phi_node->sources[1].reg;
		}
		else
		{
			pred1_reg = phi_node->sources[1].reg;
			pred2_reg = phi_node->sources[0].reg;
		}
		lima_gp_ir_store_reg_node_t* store_node =
			lima_gp_ir_store_reg_node_create();
		if (!store_node)
			return false;
		store_node->reg = phi_node->dest;
		lima_gp_ir_block_insert_start(exit, &store_node->root_node);
		for (i = 0; i < phi_node->dest->size; i++)
		{
			lima_gp_ir_alu_node_t* select_node =
				lima_gp_ir_alu_node_create(lima_gp_ir_op_select);
			if (!select_node)
			{
				lima_gp_ir_node_delete(&store_node->root_node.node);
				return false;
			}
			lima_gp_ir_load_reg_node_t* pred1_load =
				lima_gp_ir_load_reg_node_create();
			if (!pred1_load)
			{
				lima_gp_ir_node_delete(&store_node->root_node.node);
				lima_gp_ir_node_delete(&select_node->node);
				return false;
			}
			lima_gp_ir_load_reg_node_t* pred2_load =
				lima_gp_ir_load_reg_node_create();
			if (!pred2_load)
			{
				lima_gp_ir_node_delete(&store_node->root_node.node);
				lima_gp_ir_node_delete(&select_node->node);
				lima_gp_ir_node_delete(&pred2_load->node);
				return false;
			}
			pred1_load->reg = pred1_reg;
			pred1_load->component = i;
			pred2_load->reg = pred2_reg;
			pred2_load->component = i;
			select_node->children[0] = &cond->node;
			lima_gp_ir_node_link(&select_node->node, &cond->node);
			select_node->children[1] = &pred1_load->node;
			lima_gp_ir_node_link(&select_node->node, &pred1_load->node);
			select_node->children[2] = &pred2_load->node;
			lima_gp_ir_node_link(&select_node->node, &pred2_load->node);
			store_node->children[i] = &select_node->node;
			lima_gp_ir_node_link(&store_node->root_node.node,
								 &select_node->node);
			store_node->mask[i] = true;
		}
		lima_gp_ir_block_remove_phi(exit, phi_node);
	}
	return true;
}
static bool rewrite_phi_nodes ( lima_gp_ir_block_t * exit , lima_gp_ir_reg_t * cond_reg , lima_gp_ir_block_t * pred1 , lima_gp_ir_block_t * pred2 ) { unsigned i ; lima_gp_ir_load_reg_node_t * cond = lima_gp_ir_load_reg_node_create ( ) ; if ( ! cond ) return false ; cond -> reg = cond_reg ; cond -> component = 0 ; lima_gp_ir_phi_node_t * phi_node ; ptrset_iter_t iter = ptrset_iter_create ( exit -> phi_nodes ) ; ptrset_iter_for_each ( iter , phi_node ) { lima_gp_ir_reg_t * pred1_reg , * pred2_reg ; assert ( phi_node -> num_sources == 2 ) ; if ( phi_node -> sources [ 0 ] . pred == pred1 ) { pred1_reg = phi_node -> sources [ 0 ] . reg ; pred2_reg = phi_node -> sources [ 1 ] . reg ; } else { pred1_reg = phi_node -> sources [ 1 ] . reg ; pred2_reg = phi_node -> sources [ 0 ] . reg ; } lima_gp_ir_store_reg_node_t * store_node = lima_gp_ir_store_reg_node_create ( ) ; if ( ! store_node ) return false ; store_node -> reg = phi_node -> dest ; lima_gp_ir_block_insert_start ( exit , & store_node -> root_node ) ; for ( i = 0 ; i < phi_node -> dest -> size ; i ++ ) { lima_gp_ir_alu_node_t * select_node = lima_gp_ir_alu_node_create ( lima_gp_ir_op_select ) ; if ( ! select_node ) { lima_gp_ir_node_delete ( & store_node -> root_node . node ) ; return false ; } lima_gp_ir_load_reg_node_t * pred1_load = lima_gp_ir_load_reg_node_create ( ) ; if ( ! pred1_load ) { lima_gp_ir_node_delete ( & store_node -> root_node . node ) ; lima_gp_ir_node_delete ( & select_node -> node ) ; return false ; } lima_gp_ir_load_reg_node_t * pred2_load = lima_gp_ir_load_reg_node_create ( ) ; if ( ! pred2_load ) { lima_gp_ir_node_delete ( & store_node -> root_node . node ) ; lima_gp_ir_node_delete ( & select_node -> node ) ; lima_gp_ir_node_delete ( & pred2_load -> node ) ; return false ; } pred1_load -> reg = pred1_reg ; pred1_load -> component = i ; pred2_load -> reg = pred2_reg ; pred2_load -> component = i ; select_node -> children [ 0 ] = & cond -> node ; lima_gp_ir_node_link ( & select_node -> node , & cond -> node ) ; select_node -> children [ 1 ] = & pred1_load -> node ; lima_gp_ir_node_link ( & select_node -> node , & pred1_load -> node ) ; select_node -> children [ 2 ] = & pred2_load -> node ; lima_gp_ir_node_link ( & select_node -> node , & pred2_load -> node ) ; store_node -> children [ i ] = & select_node -> node ; lima_gp_ir_node_link ( & store_node -> root_node . node , & select_node -> node ) ; store_node -> mask [ i ] = true ; } lima_gp_ir_block_remove_phi ( exit , phi_node ) ; } return true ; }
Rewrites phi nodes in the exit block to use selects instead
cond_reg must be true if pred1 was taken, false if pred2 was taken
Rewrites phi nodes in the exit block to use selects instead cond_reg must be true if pred1 was taken false if pred2 was taken