static void pair_sub_for_all_args(
	struct rc_instruction * fullinst,
	struct rc_pair_sub_instruction * sub,
	rc_pair_read_arg_fn cb,
	void * userdata)
{
	int i;
	const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode);

	for(i = 0; i < info->NumSrcRegs; i++) {
		unsigned int src_type;

		src_type = rc_source_type_swz(sub->Arg[i].Swizzle);

		if (src_type == RC_SOURCE_NONE)
			continue;

		if (sub->Arg[i].Source == RC_PAIR_PRESUB_SRC) {
			unsigned int presub_type;
			unsigned int presub_src_count;
			struct rc_pair_instruction_source * src_array;
			unsigned int j;

			if (src_type & RC_SOURCE_RGB) {
				presub_type = fullinst->
					U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Index;
				src_array = fullinst->U.P.RGB.Src;
			} else {
				presub_type = fullinst->
					U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Index;
				src_array = fullinst->U.P.Alpha.Src;
			}
			presub_src_count
				= rc_presubtract_src_reg_count(presub_type);
			for(j = 0; j < presub_src_count; j++) {
				cb(userdata, fullinst, &sub->Arg[i],
								&src_array[j]);
			}
		} else {
			struct rc_pair_instruction_source * src =
				rc_pair_get_src(&fullinst->U.P, &sub->Arg[i]);
			if (src) {
				cb(userdata, fullinst, &sub->Arg[i], src);
			}
		}
	}
}
static void mark_used(
	struct rc_instruction * inst,
	struct rc_pair_sub_instruction * sub)
{
	unsigned int i;
	const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode);
	for (i = 0; i < info->NumSrcRegs; i++) {
		unsigned int src_type = rc_source_type_swz(sub->Arg[i].Swizzle);
		if (src_type & RC_SOURCE_RGB) {
			inst->U.P.RGB.Src[sub->Arg[i].Source].Used = 1;
		}

		if (src_type & RC_SOURCE_ALPHA) {
			inst->U.P.Alpha.Src[sub->Arg[i].Source].Used = 1;
		}
	}
}
/* This is a helper function for destructive_merge_instructions().  It helps
 * merge presubtract sources from two instructions and makes sure the
 * presubtract sources end up in the correct spot.  This function assumes that
 * dst_full is an rgb instruction, meaning that it has a vector instruction(rgb)
 * but no scalar instruction (alpha).
 * @return 0 if merging the presubtract sources fails.
 * @retrun 1 if merging the presubtract sources succeeds.
 */
static int merge_presub_sources(
	struct rc_pair_instruction * dst_full,
	struct rc_pair_sub_instruction src,
	unsigned int type)
{
	unsigned int srcp_src, srcp_regs, is_rgb, is_alpha;
	struct rc_pair_sub_instruction * dst_sub;
	const struct rc_opcode_info * info;

	assert(dst_full->Alpha.Opcode == RC_OPCODE_NOP);

	switch(type) {
	case RC_SOURCE_RGB:
		is_rgb = 1;
		is_alpha = 0;
		dst_sub = &dst_full->RGB;
		break;
	case RC_SOURCE_ALPHA:
		is_rgb = 0;
		is_alpha = 1;
		dst_sub = &dst_full->Alpha;
		break;
	default:
		assert(0);
		return 0;
	}

	info = rc_get_opcode_info(dst_full->RGB.Opcode);

	if (dst_sub->Src[RC_PAIR_PRESUB_SRC].Used)
		return 0;

	srcp_regs = rc_presubtract_src_reg_count(
					src.Src[RC_PAIR_PRESUB_SRC].Index);
	for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) {
		unsigned int arg;
		int free_source;
		unsigned int one_way = 0;
		struct rc_pair_instruction_source srcp = src.Src[srcp_src];
		struct rc_pair_instruction_source temp;

		free_source = rc_pair_alloc_source(dst_full, is_rgb, is_alpha,
							srcp.File, srcp.Index);

		/* If free_source < 0 then there are no free source
		 * slots. */
		if (free_source < 0)
			return 0;

		temp = dst_sub->Src[srcp_src];
		dst_sub->Src[srcp_src] = dst_sub->Src[free_source];

		/* srcp needs src0 and src1 to be the same */
		if (free_source < srcp_src) {
			if (!temp.Used)
				continue;
			free_source = rc_pair_alloc_source(dst_full, is_rgb,
					is_alpha, temp.File, temp.Index);
			if (free_source < 0)
				return 0;
			one_way = 1;
		} else {
			dst_sub->Src[free_source] = temp;
		}

		/* If free_source == srcp_src, then the presubtract
		 * source is already in the correct place. */
		if (free_source == srcp_src)
			continue;

		/* Shuffle the sources, so we can put the
		 * presubtract source in the correct place. */
		for(arg = 0; arg < info->NumSrcRegs; arg++) {
			/*If this arg does not read from an rgb source,
			 * do nothing. */
			if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle,
								3) & type)) {
				continue;
			}

			if (dst_full->RGB.Arg[arg].Source == srcp_src)
				dst_full->RGB.Arg[arg].Source = free_source;
			/* We need to do this just in case register
			 * is one of the sources already, but in the
			 * wrong spot. */
			else if(dst_full->RGB.Arg[arg].Source == free_source
							&& !one_way) {
				dst_full->RGB.Arg[arg].Source = srcp_src;
			}
		}
	}
	return 1;
}