コード例 #1
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
/**
 * IF Temp[0].x -\
 * KILP         - > KIL -abs(Temp[0].x)
 * ENDIF        -/
 *
 * This needs to be done in its own pass, because it modifies the instructions
 * before and after KILP.
 */
void rc_transform_KILP(struct radeon_compiler * c, void *user)
{
	struct rc_instruction * inst;
	for (inst = c->Program.Instructions.Next;
			inst != &c->Program.Instructions; inst = inst->Next) {

		if (inst->U.I.Opcode != RC_OPCODE_KILP)
			continue;

		inst->U.I.Opcode = RC_OPCODE_KIL;

		if (inst->Prev->U.I.Opcode != RC_OPCODE_IF
				|| inst->Next->U.I.Opcode != RC_OPCODE_ENDIF) {
			inst->U.I.SrcReg[0] = negate(builtin_one);
		} else {

			inst->U.I.SrcReg[0] =
				negate(absolute(inst->Prev->U.I.SrcReg[0]));
			/* Remove IF */
			rc_remove_instruction(inst->Prev);
			/* Remove ENDIF */
			rc_remove_instruction(inst->Next);
		}
	}
}
コード例 #2
0
/**
 * This function prepares a loop to be unrolled by converting it into an if
 * statement.  Here is an outline of the conversion process:
 * BGNLOOP;                         	-> BGNLOOP;
 * <Additional conditional code>	-> <Additional conditional code>
 * SGE/SLT temp[0], temp[1], temp[2];	-> SLT/SGE temp[0], temp[1], temp[2];
 * IF temp[0];                      	-> IF temp[0];
 * BRK;                             	->
 * ENDIF;                           	-> <Loop Body>
 * <Loop Body>                      	-> ENDIF;
 * ENDLOOP;                         	-> ENDLOOP
 *
 * @param inst A pointer to a BGNLOOP instruction.
 * @return 1 for success, 0 for failure
 */
static int transform_loop(struct emulate_loop_state * s,
						struct rc_instruction * inst)
{
	struct loop_info * loop;

	memory_pool_array_reserve(&s->C->Pool, struct loop_info,
			s->Loops, s->LoopCount, s->LoopReserved, 1);

	loop = &s->Loops[s->LoopCount++];

	if (!build_loop_info(s->C, loop, inst)) {
		rc_error(s->C, "Failed to build loop info\n");
		return 0;
	}

	if(try_unroll_loop(s->C, loop)){
		return 1;
	}

	/* Reverse the conditional instruction */
	switch(loop->Cond->U.I.Opcode){
	case RC_OPCODE_SGE:
		loop->Cond->U.I.Opcode = RC_OPCODE_SLT;
		break;
	case RC_OPCODE_SLT:
		loop->Cond->U.I.Opcode = RC_OPCODE_SGE;
		break;
	case RC_OPCODE_SLE:
		loop->Cond->U.I.Opcode = RC_OPCODE_SGT;
		break;
	case RC_OPCODE_SGT:
		loop->Cond->U.I.Opcode = RC_OPCODE_SLE;
		break;
	case RC_OPCODE_SEQ:
		loop->Cond->U.I.Opcode = RC_OPCODE_SNE;
		break;
	case RC_OPCODE_SNE:
		loop->Cond->U.I.Opcode = RC_OPCODE_SEQ;
		break;
	default:
		rc_error(s->C, "loop->Cond is not a conditional.\n");
		return 0;
	}

	/* Prepare the loop to be emulated */
	rc_remove_instruction(loop->Brk);
	rc_remove_instruction(loop->EndIf);
	rc_insert_instruction(loop->EndLoop->Prev, loop->EndIf);
	return 1;
}
コード例 #3
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_r300_vertex_CMP(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	/* There is no decent CMP available, so let's rig one up.
	 * CMP is defined as dst = src0 < 0.0 ? src1 : src2
	 * The following sequence consumes zero to two temps and two extra slots
	 * (the second temp and the second slot is consumed by transform_LRP),
	 * but should be equivalent:
	 *
	 * SLT tmp0, src0, 0.0
	 * LRP dst, tmp0, src1, src2
	 *
	 * Yes, I know, I'm a mad scientist. ~ C. & M. */
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);

	/* SLT tmp0, src0, 0.0 */
	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
		dst,
		inst->U.I.SrcReg[0], builtin_zero);

	/* LRP dst, tmp0, src1, src2 */
	transform_LRP(c,
		emit3(c, inst->Prev, RC_OPCODE_LRP, 0,
		      inst->U.I.DstReg,
		      srcreg(RC_FILE_TEMPORARY, dst.Index), inst->U.I.SrcReg[1],  inst->U.I.SrcReg[2]));

	rc_remove_instruction(inst);
}
コード例 #4
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_r300_vertex_SEQ(struct radeon_compiler *c,
	struct rc_instruction *inst)
{
	/* x = y  <==>  x >= y && y >= x */
	int tmp = rc_find_free_temporary(c);

	/* x <= y */
	emit2(c, inst->Prev, RC_OPCODE_SGE, 0,
	      dstregtmpmask(tmp, inst->U.I.DstReg.WriteMask),
	      inst->U.I.SrcReg[0],
	      inst->U.I.SrcReg[1]);

	/* y <= x */
	emit2(c, inst->Prev, RC_OPCODE_SGE, 0,
	      inst->U.I.DstReg,
	      inst->U.I.SrcReg[1],
	      inst->U.I.SrcReg[0]);

	/* x && y  =  x * y */
	emit2(c, inst->Prev, RC_OPCODE_MUL, 0,
	      inst->U.I.DstReg,
	      srcreg(RC_FILE_TEMPORARY, tmp),
	      srcreg(inst->U.I.DstReg.File, inst->U.I.DstReg.Index));

	rc_remove_instruction(inst);
}
コード例 #5
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_r300_vertex_SNE(struct radeon_compiler *c,
	struct rc_instruction *inst)
{
	/* x != y  <==>  x < y || y < x */
	int tmp = rc_find_free_temporary(c);

	/* x < y */
	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
	      dstregtmpmask(tmp, inst->U.I.DstReg.WriteMask),
	      inst->U.I.SrcReg[0],
	      inst->U.I.SrcReg[1]);

	/* y < x */
	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
	      inst->U.I.DstReg,
	      inst->U.I.SrcReg[1],
	      inst->U.I.SrcReg[0]);

	/* x || y  =  max(x, y) */
	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
	      inst->U.I.DstReg,
	      srcreg(RC_FILE_TEMPORARY, tmp),
	      srcreg(inst->U.I.DstReg.File, inst->U.I.DstReg.Index));

	rc_remove_instruction(inst);
}
コード例 #6
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_r300_vertex_SSG(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	/* result = sign(x)
	 *
	 *   SLT tmp0, 0, x;
	 *   SLT tmp1, x, 0;
	 *   ADD result, tmp0, -tmp1;
	 */
	struct rc_dst_register dst0 = try_to_reuse_dst(c, inst);
	unsigned tmp1;

	/* 0 < x */
	dst0 = try_to_reuse_dst(c, inst);
	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
	      dst0,
	      builtin_zero,
	      inst->U.I.SrcReg[0]);

	/* x < 0 */
	tmp1 = rc_find_free_temporary(c);
	emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
	      dstregtmpmask(tmp1, inst->U.I.DstReg.WriteMask),
	      inst->U.I.SrcReg[0],
	      builtin_zero);

	/* Either both are zero, or one of them is one and the other is zero. */
	/* result = tmp0 - tmp1 */
	emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
	      inst->U.I.DstReg,
	      srcreg(RC_FILE_TEMPORARY, dst0.Index),
	      negate(srcreg(RC_FILE_TEMPORARY, tmp1)));

	rc_remove_instruction(inst);
}
コード例 #7
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void r300_transform_SIN_COS_SCS(struct radeon_compiler *c,
	struct rc_instruction *inst,
	unsigned srctmp)
{
	if (inst->U.I.Opcode == RC_OPCODE_COS) {
		emit1(c, inst->Prev, RC_OPCODE_COS, inst->U.I.SaturateMode, inst->U.I.DstReg,
			srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
	} else if (inst->U.I.Opcode == RC_OPCODE_SIN) {
		emit1(c, inst->Prev, RC_OPCODE_SIN, inst->U.I.SaturateMode,
			inst->U.I.DstReg, srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
	} else if (inst->U.I.Opcode == RC_OPCODE_SCS) {
		struct rc_dst_register moddst = inst->U.I.DstReg;

		if (inst->U.I.DstReg.WriteMask & RC_MASK_X) {
			moddst.WriteMask = RC_MASK_X;
			emit1(c, inst->Prev, RC_OPCODE_COS, inst->U.I.SaturateMode, moddst,
				srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
		}
		if (inst->U.I.DstReg.WriteMask & RC_MASK_Y) {
			moddst.WriteMask = RC_MASK_Y;
			emit1(c, inst->Prev, RC_OPCODE_SIN, inst->U.I.SaturateMode, moddst,
				srcregswz(RC_FILE_TEMPORARY, srctmp, RC_SWIZZLE_WWWW));
		}
	}

	rc_remove_instruction(inst);
}
コード例 #8
0
/* dst = ROUND(src) :
 *   add = src + .5
 *   frac = FRC(add)
 *   dst = add - frac
 *
 * According to the GLSL spec, the implementor can decide which way to round
 * when the fraction is .5.  We round down for .5.
 *
 */
static void transform_ROUND(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	unsigned int mask = inst->U.I.DstReg.WriteMask;
	unsigned int frac_index, add_index;
	struct rc_dst_register frac_dst, add_dst;
	struct rc_src_register frac_src, add_src;

	/* add = src + .5 */
	add_index = rc_find_free_temporary(c);
	add_dst = dstregtmpmask(add_index, mask);
	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, add_dst, inst->U.I.SrcReg[0],
								builtin_half);
	add_src = srcreg(RC_FILE_TEMPORARY, add_dst.Index);


	/* frac = FRC(add) */
	frac_index = rc_find_free_temporary(c);
	frac_dst = dstregtmpmask(frac_index, mask);
	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, frac_dst, add_src);
	frac_src = srcreg(RC_FILE_TEMPORARY, frac_dst.Index);

	/* dst = add - frac */
	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, inst->U.I.DstReg,
						add_src, negate(frac_src));
	rc_remove_instruction(inst);
}
コード例 #9
0
/**
 * IF Temp[0].x -> IF Temp[0].x
 * ...          -> ...
 * KILP         -> KIL -abs(Temp[0].x)
 * ...          -> ...
 * ENDIF        -> ENDIF
 *
 * === OR ===
 *
 * IF Temp[0].x -\
 * KILP         - > KIL -abs(Temp[0].x)
 * ENDIF        -/
 *
 * === OR ===
 *
 * IF Temp[0].x -> IF Temp[0].x
 * ...          -> ...
 * ELSE         -> ELSE
 * ...	        -> ...
 * KILP	        -> KIL -abs(Temp[0].x)
 * ...          -> ...
 * ENDIF        -> ENDIF
 *
 * === OR ===
 *
 * KILP         -> KIL -none.1111
 *
 * This needs to be done in its own pass, because it might modify the
 * instructions before and after KILP.
 */
void rc_transform_KILP(struct radeon_compiler * c, void *user)
{
	struct rc_instruction * inst;
	for (inst = c->Program.Instructions.Next;
			inst != &c->Program.Instructions; inst = inst->Next) {
		struct rc_instruction * if_inst;
		unsigned in_if = 0;

		if (inst->U.I.Opcode != RC_OPCODE_KILP)
			continue;

		for (if_inst = inst->Prev; if_inst != &c->Program.Instructions;
						if_inst = if_inst->Prev) {

			if (if_inst->U.I.Opcode == RC_OPCODE_IF) {
				in_if = 1;
				break;
			}
		}

		inst->U.I.Opcode = RC_OPCODE_KIL;

		if (!in_if) {
			inst->U.I.SrcReg[0] = negate(builtin_one);
		} else {
			/* This should work even if the KILP is inside the ELSE
			 * block, because -0.0 is considered negative. */
			inst->U.I.SrcReg[0] =
				negate(absolute(if_inst->U.I.SrcReg[0]));

			if (inst->Prev->U.I.Opcode != RC_OPCODE_IF
				&& inst->Next->U.I.Opcode != RC_OPCODE_ENDIF) {

				/* Optimize the special case:
				 * IF Temp[0].x
				 * KILP
				 * ENDIF
				 */

				/* Remove IF */
				rc_remove_instruction(inst->Prev);
				/* Remove ENDIF */
				rc_remove_instruction(inst->Next);
			}
		}
	}
}
コード例 #10
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
/**
 * [1, src0.y*src1.y, src0.z, src1.w]
 * So basically MUL with lotsa swizzling.
 */
static void transform_DST(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	emit2(c, inst->Prev, RC_OPCODE_MUL, inst->U.I.SaturateMode, inst->U.I.DstReg,
		swizzle(inst->U.I.SrcReg[0], RC_SWIZZLE_ONE, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_ONE),
		swizzle(inst->U.I.SrcReg[1], RC_SWIZZLE_ONE, RC_SWIZZLE_Y, RC_SWIZZLE_ONE, RC_SWIZZLE_W));
	rc_remove_instruction(inst);
}
コード例 #11
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_ABS(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_src_register src = inst->U.I.SrcReg[0];
	src.Abs = 1;
	src.Negate = RC_MASK_NONE;
	emit1(c, inst->Prev, RC_OPCODE_MOV, inst->U.I.SaturateMode, inst->U.I.DstReg, src);
	rc_remove_instruction(inst);
}
コード例 #12
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_FLR(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, inst->U.I.SrcReg[0]);
	emit2(c, inst->Prev, RC_OPCODE_ADD, inst->U.I.SaturateMode, inst->U.I.DstReg,
		inst->U.I.SrcReg[0], negate(srcreg(RC_FILE_TEMPORARY, dst.Index)));
	rc_remove_instruction(inst);
}
コード例 #13
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_DPH(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_src_register src0 = inst->U.I.SrcReg[0];
	src0.Negate &= ~RC_MASK_W;
	src0.Swizzle &= ~(7 << (3 * 3));
	src0.Swizzle |= RC_SWIZZLE_ONE << (3 * 3);
	emit2(c, inst->Prev, RC_OPCODE_DP4, inst->U.I.SaturateMode, inst->U.I.DstReg, src0, inst->U.I.SrcReg[1]);
	rc_remove_instruction(inst);
}
コード例 #14
0
static void unroll_loop(struct radeon_compiler * c, struct loop_info * loop,
						unsigned int iterations)
{
	unsigned int i;
	struct rc_instruction * ptr;
	struct rc_instruction * first = loop->BeginLoop->Next;
	struct rc_instruction * last = loop->EndLoop->Prev;
	struct rc_instruction * append_to = last;
	rc_remove_instruction(loop->BeginLoop);
	rc_remove_instruction(loop->EndLoop);
	for( i = 1; i < iterations; i++){
		for(ptr = first; ptr != last->Next; ptr = ptr->Next){
			struct rc_instruction *new = rc_alloc_instruction(c);
			memcpy(new, ptr, sizeof(struct rc_instruction));
			rc_insert_instruction(append_to, new);
			append_to = new;
		}
	}
}
コード例 #15
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_SNE(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);

	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, inst->U.I.SrcReg[0], negate(inst->U.I.SrcReg[1]));
	emit3(c, inst->Prev, RC_OPCODE_CMP, inst->U.I.SaturateMode, inst->U.I.DstReg,
		negate(absolute(srcreg(RC_FILE_TEMPORARY, dst.Index))), builtin_one, builtin_zero);

	rc_remove_instruction(inst);
}
コード例 #16
0
static void transform_SLE(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);

	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, negate(inst->U.I.SrcReg[0]), inst->U.I.SrcReg[1]);
	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg,
		srcreg(RC_FILE_TEMPORARY, dst.Index), builtin_zero, builtin_one);

	rc_remove_instruction(inst);
}
コード例 #17
0
static void transform_LRP(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);

	emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
		dst,
		inst->U.I.SrcReg[1], negate(inst->U.I.SrcReg[2]));
	emit3(c, inst->Prev, RC_OPCODE_MAD, &inst->U.I,
		inst->U.I.DstReg,
		inst->U.I.SrcReg[0], srcreg(RC_FILE_TEMPORARY, dst.Index), inst->U.I.SrcReg[2]);

	rc_remove_instruction(inst);
}
コード例 #18
0
static void transform_r300_vertex_DP3(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_src_register src0 = inst->U.I.SrcReg[0];
	struct rc_src_register src1 = inst->U.I.SrcReg[1];
	src0.Negate &= ~RC_MASK_W;
	src0.Swizzle &= ~(7 << (3 * 3));
	src0.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
	src1.Negate &= ~RC_MASK_W;
	src1.Swizzle &= ~(7 << (3 * 3));
	src1.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
	emit2(c, inst->Prev, RC_OPCODE_DP4, &inst->U.I, inst->U.I.DstReg, src0, src1);
	rc_remove_instruction(inst);
}
コード例 #19
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_DP2(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_src_register src0 = inst->U.I.SrcReg[0];
	struct rc_src_register src1 = inst->U.I.SrcReg[1];
	src0.Negate &= ~(RC_MASK_Z | RC_MASK_W);
	src0.Swizzle &= ~(63 << (3 * 2));
	src0.Swizzle |= (RC_SWIZZLE_ZERO << (3 * 2)) | (RC_SWIZZLE_ZERO << (3 * 3));
	src1.Negate &= ~(RC_MASK_Z | RC_MASK_W);
	src1.Swizzle &= ~(63 << (3 * 2));
	src1.Swizzle |= (RC_SWIZZLE_ZERO << (3 * 2)) | (RC_SWIZZLE_ZERO << (3 * 3));
	emit2(c, inst->Prev, RC_OPCODE_DP3, inst->U.I.SaturateMode, inst->U.I.DstReg, src0, src1);
	rc_remove_instruction(inst);
}
コード例 #20
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_POW(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register tempdst = try_to_reuse_dst(c, inst);
	struct rc_src_register tempsrc = srcreg(RC_FILE_TEMPORARY, tempdst.Index);
	tempdst.WriteMask = RC_MASK_W;
	tempsrc.Swizzle = RC_SWIZZLE_WWWW;

	emit1(c, inst->Prev, RC_OPCODE_LG2, 0, tempdst, swizzle_xxxx(inst->U.I.SrcReg[0]));
	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, tempdst, tempsrc, swizzle_xxxx(inst->U.I.SrcReg[1]));
	emit1(c, inst->Prev, RC_OPCODE_EX2, inst->U.I.SaturateMode, inst->U.I.DstReg, tempsrc);

	rc_remove_instruction(inst);
}
コード例 #21
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_CLAMP(struct radeon_compiler *c,
	struct rc_instruction *inst)
{
	/* CLAMP dst, src, min, max
	 *    into:
	 * MIN tmp, src, max
	 * MAX dst, tmp, min
	 */
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
	emit2(c, inst->Prev, RC_OPCODE_MIN, 0, dst,
		inst->U.I.SrcReg[0], inst->U.I.SrcReg[2]);
	emit2(c, inst->Prev, RC_OPCODE_MAX, inst->U.I.SaturateMode, inst->U.I.DstReg,
		srcreg(RC_FILE_TEMPORARY, dst.Index), inst->U.I.SrcReg[1]);
	rc_remove_instruction(inst);
}
コード例 #22
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_XPD(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);

	emit2(c, inst->Prev, RC_OPCODE_MUL, 0, dst,
		swizzle(inst->U.I.SrcReg[0], RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_W),
		swizzle(inst->U.I.SrcReg[1], RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_W));
	emit3(c, inst->Prev, RC_OPCODE_MAD, inst->U.I.SaturateMode, inst->U.I.DstReg,
		swizzle(inst->U.I.SrcReg[0], RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_W),
		swizzle(inst->U.I.SrcReg[1], RC_SWIZZLE_Z, RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_W),
		negate(srcreg(RC_FILE_TEMPORARY, dst.Index)));

	rc_remove_instruction(inst);
}
コード例 #23
0
static void transform_TRUNC(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	/* Definition of trunc:
	 *   trunc(x) = (abs(x) - fract(abs(x))) * sgn(x)
	 *
	 * The multiplication by sgn(x) can be simplified using CMP:
	 *   y * sgn(x) = (x < 0 ? -y : y)
	 */
	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, absolute(inst->U.I.SrcReg[0]));
	emit2(c, inst->Prev, RC_OPCODE_ADD, 0, dst, absolute(inst->U.I.SrcReg[0]),
	      negate(srcreg(RC_FILE_TEMPORARY, dst.Index)));
	emit3(c, inst->Prev, RC_OPCODE_CMP, &inst->U.I, inst->U.I.DstReg, inst->U.I.SrcReg[0],
	      negate(srcreg(RC_FILE_TEMPORARY, dst.Index)), srcreg(RC_FILE_TEMPORARY, dst.Index));
	rc_remove_instruction(inst);
}
コード例 #24
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_CEIL(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	/* Assuming:
	 *     ceil(x) = -floor(-x)
	 *
	 * After inlining floor:
	 *     ceil(x) = -(-x-frac(-x))
	 *
	 * After simplification:
	 *     ceil(x) = x+frac(-x)
	 */

	struct rc_dst_register dst = try_to_reuse_dst(c, inst);
	emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dst, negate(inst->U.I.SrcReg[0]));
	emit2(c, inst->Prev, RC_OPCODE_ADD, inst->U.I.SaturateMode, inst->U.I.DstReg,
		inst->U.I.SrcReg[0], srcreg(RC_FILE_TEMPORARY, dst.Index));
	rc_remove_instruction(inst);
}
コード例 #25
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
/**
 * Definition of LIT (from ARB_fragment_program):
 *
 *  tmp = VectorLoad(op0);
 *  if (tmp.x < 0) tmp.x = 0;
 *  if (tmp.y < 0) tmp.y = 0;
 *  if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
 *  else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
 *  result.x = 1.0;
 *  result.y = tmp.x;
 *  result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
 *  result.w = 1.0;
 *
 * The longest path of computation is the one leading to result.z,
 * consisting of 5 operations. This implementation of LIT takes
 * 5 slots, if the subsequent optimization passes are clever enough
 * to pair instructions correctly.
 */
static void transform_LIT(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	unsigned int constant;
	unsigned int constant_swizzle;
	unsigned int temp;
	struct rc_src_register srctemp;

	constant = rc_constants_add_immediate_scalar(&c->Program.Constants, -127.999999, &constant_swizzle);

	if (inst->U.I.DstReg.WriteMask != RC_MASK_XYZW || inst->U.I.DstReg.File != RC_FILE_TEMPORARY) {
		struct rc_instruction * inst_mov;

		inst_mov = emit1(c, inst,
			RC_OPCODE_MOV, 0, inst->U.I.DstReg,
			srcreg(RC_FILE_TEMPORARY, rc_find_free_temporary(c)));

		inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
		inst->U.I.DstReg.Index = inst_mov->U.I.SrcReg[0].Index;
		inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
	}

	temp = inst->U.I.DstReg.Index;
	srctemp = srcreg(RC_FILE_TEMPORARY, temp);

	/* tmp.x = max(0.0, Src.x); */
	/* tmp.y = max(0.0, Src.y); */
	/* tmp.w = clamp(Src.z, -128+eps, 128-eps); */
	emit2(c, inst->Prev, RC_OPCODE_MAX, 0,
		dstregtmpmask(temp, RC_MASK_XYW),
		inst->U.I.SrcReg[0],
		swizzle(srcreg(RC_FILE_CONSTANT, constant),
			RC_SWIZZLE_ZERO, RC_SWIZZLE_ZERO, RC_SWIZZLE_ZERO, constant_swizzle&3));
	emit2(c, inst->Prev, RC_OPCODE_MIN, 0,
		dstregtmpmask(temp, RC_MASK_Z),
		swizzle_wwww(srctemp),
		negate(srcregswz(RC_FILE_CONSTANT, constant, constant_swizzle)));

	/* tmp.w = Pow(tmp.y, tmp.w) */
	emit1(c, inst->Prev, RC_OPCODE_LG2, 0,
		dstregtmpmask(temp, RC_MASK_W),
		swizzle_yyyy(srctemp));
	emit2(c, inst->Prev, RC_OPCODE_MUL, 0,
		dstregtmpmask(temp, RC_MASK_W),
		swizzle_wwww(srctemp),
		swizzle_zzzz(srctemp));
	emit1(c, inst->Prev, RC_OPCODE_EX2, 0,
		dstregtmpmask(temp, RC_MASK_W),
		swizzle_wwww(srctemp));

	/* tmp.z = (tmp.x > 0) ? tmp.w : 0.0 */
	emit3(c, inst->Prev, RC_OPCODE_CMP, inst->U.I.SaturateMode,
		dstregtmpmask(temp, RC_MASK_Z),
		negate(swizzle_xxxx(srctemp)),
		swizzle_wwww(srctemp),
		builtin_zero);

	/* tmp.x, tmp.y, tmp.w = 1.0, tmp.x, 1.0 */
	emit1(c, inst->Prev, RC_OPCODE_MOV, inst->U.I.SaturateMode,
		dstregtmpmask(temp, RC_MASK_XYW),
		swizzle(srctemp, RC_SWIZZLE_ONE, RC_SWIZZLE_X, RC_SWIZZLE_ONE, RC_SWIZZLE_ONE));

	rc_remove_instruction(inst);
}
コード例 #26
0
/**
 * If c->max_alu_inst is -1, then all eligible loops will be unrolled regardless
 * of how many iterations they have.
 */
static int try_unroll_loop(struct radeon_compiler * c, struct loop_info * loop)
{
	int end_loops;
	int iterations;
	struct count_inst count_inst;
	float limit_value;
	struct rc_src_register * counter;
	struct rc_src_register * limit;
	struct const_value counter_value;
	struct rc_instruction * inst;

	/* Find the counter and the upper limit */

	if(rc_src_reg_is_immediate(c, loop->Cond->U.I.SrcReg[0].File,
					loop->Cond->U.I.SrcReg[0].Index)){
		limit = &loop->Cond->U.I.SrcReg[0];
		counter = &loop->Cond->U.I.SrcReg[1];
	}
	else if(rc_src_reg_is_immediate(c, loop->Cond->U.I.SrcReg[1].File,
					loop->Cond->U.I.SrcReg[1].Index)){
		limit = &loop->Cond->U.I.SrcReg[1];
		counter = &loop->Cond->U.I.SrcReg[0];
	}
	else{
		DBG("No constant limit.\n");
		return 0;
	}

	/* Find the initial value of the counter */
	counter_value.Src = counter;
	counter_value.Value = 0.0f;
	counter_value.HasValue = 0;
	counter_value.C = c;
	for(inst = c->Program.Instructions.Next; inst != loop->BeginLoop;
							inst = inst->Next){
		rc_for_all_writes_mask(inst, update_const_value, &counter_value);
	}
	if(!counter_value.HasValue){
		DBG("Initial counter value cannot be determined.\n");
		return 0;
	}
	DBG("Initial counter value is %f\n", counter_value.Value);
	/* Determine how the counter is modified each loop */
	count_inst.C = c;
	count_inst.Index = counter->Index;
	count_inst.Swz = counter->Swizzle;
	count_inst.Amount = 0.0f;
	count_inst.Unknown = 0;
	count_inst.BranchDepth = 0;
	end_loops = 1;
	for(inst = loop->BeginLoop->Next; end_loops > 0; inst = inst->Next){
		switch(inst->U.I.Opcode){
		/* XXX In the future we might want to try to unroll nested
		 * loops here.*/
		case RC_OPCODE_BGNLOOP:
			end_loops++;
			break;
		case RC_OPCODE_ENDLOOP:
			loop->EndLoop = inst;
			end_loops--;
			break;
		case RC_OPCODE_BRK:
			/* Don't unroll loops if it has a BRK instruction
			 * other one used when testing the main conditional
			 * of the loop. */

			/* Make sure we haven't entered a nested loops. */
			if(inst != loop->Brk && end_loops == 1) {
				return 0;
			}
			break;
		case RC_OPCODE_IF:
			count_inst.BranchDepth++;
			break;
		case RC_OPCODE_ENDIF:
			count_inst.BranchDepth--;
			break;
		default:
			rc_for_all_writes_mask(inst, get_incr_amount, &count_inst);
			if(count_inst.Unknown){
				return 0;
			}
			break;
		}
	}
	/* Infinite loop */
	if(count_inst.Amount == 0.0f){
		return 0;
	}
	DBG("Counter is increased by %f each iteration.\n", count_inst.Amount);
	/* Calculate the number of iterations of this loop.  Keeping this
	 * simple, since we only support increment and decrement loops.
	 */
	limit_value = rc_get_constant_value(c, limit->Index, limit->Swizzle,
							limit->Negate, 0);
	DBG("Limit is %f.\n", limit_value);
	/* The iteration calculations are opposite of what you would expect.
	 * In a normal loop, if the condition is met, then loop continues, but
	 * with our loops, if the condition is met, the is exited. */
	switch(loop->Cond->U.I.Opcode){
	case RC_OPCODE_SGE:
	case RC_OPCODE_SLE:
		iterations = (int) ceilf((limit_value - counter_value.Value) /
							count_inst.Amount);
		break;

	case RC_OPCODE_SGT:
	case RC_OPCODE_SLT:
		iterations = (int) floorf((limit_value - counter_value.Value) /
							count_inst.Amount) + 1;
		break;
	default:
		return 0;
	}

	if (c->max_alu_insts > 0
		&& iterations > loop_max_possible_iterations(c, loop)) {
		return 0;
	}

	DBG("Loop will have %d iterations.\n", iterations);

	/* Prepare loop for unrolling */
	rc_remove_instruction(loop->Cond);
	rc_remove_instruction(loop->If);
	rc_remove_instruction(loop->Brk);
	rc_remove_instruction(loop->EndIf);

	unroll_loop(c, loop, iterations);
	loop->EndLoop = NULL;
	return 1;
}
コード例 #27
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
/**
 * Translate the trigonometric functions COS, SIN, and SCS
 * using only the basic instructions
 *  MOV, ADD, MUL, MAD, FRC
 */
int r300_transform_trig_simple(struct radeon_compiler* c,
	struct rc_instruction* inst,
	void* unused)
{
	unsigned int constants[2];
	unsigned int tempreg;

	if (inst->U.I.Opcode != RC_OPCODE_COS &&
	    inst->U.I.Opcode != RC_OPCODE_SIN &&
	    inst->U.I.Opcode != RC_OPCODE_SCS)
		return 0;

	tempreg = rc_find_free_temporary(c);

	sincos_constants(c, constants);

	if (inst->U.I.Opcode == RC_OPCODE_COS) {
		/* MAD tmp.x, src, 1/(2*PI), 0.75 */
		/* FRC tmp.x, tmp.x */
		/* MAD tmp.z, tmp.x, 2*PI, -PI */
		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
			swizzle_xxxx(inst->U.I.SrcReg[0]),
			swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[1])),
			swizzle_xxxx(srcreg(RC_FILE_CONSTANT, constants[1])));
		emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(tempreg, RC_MASK_W),
			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)));
		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
			swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[1])),
			negate(swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[0]))));

		sin_approx(c, inst, inst->U.I.DstReg,
			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
			constants);
	} else if (inst->U.I.Opcode == RC_OPCODE_SIN) {
		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
			swizzle_xxxx(inst->U.I.SrcReg[0]),
			swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[1])),
			swizzle_yyyy(srcreg(RC_FILE_CONSTANT, constants[1])));
		emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(tempreg, RC_MASK_W),
			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)));
		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_W),
			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
			swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[1])),
			negate(swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[0]))));

		sin_approx(c, inst, inst->U.I.DstReg,
			swizzle_wwww(srcreg(RC_FILE_TEMPORARY, tempreg)),
			constants);
	} else {
		struct rc_dst_register dst;

		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_XY),
			swizzle_xxxx(inst->U.I.SrcReg[0]),
			swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[1])),
			swizzle(srcreg(RC_FILE_CONSTANT, constants[1]), RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_W));
		emit1(c, inst->Prev, RC_OPCODE_FRC, 0, dstregtmpmask(tempreg, RC_MASK_XY),
			srcreg(RC_FILE_TEMPORARY, tempreg));
		emit3(c, inst->Prev, RC_OPCODE_MAD, 0, dstregtmpmask(tempreg, RC_MASK_XY),
			srcreg(RC_FILE_TEMPORARY, tempreg),
			swizzle_wwww(srcreg(RC_FILE_CONSTANT, constants[1])),
			negate(swizzle_zzzz(srcreg(RC_FILE_CONSTANT, constants[0]))));

		dst = inst->U.I.DstReg;

		dst.WriteMask = inst->U.I.DstReg.WriteMask & RC_MASK_X;
		sin_approx(c, inst, dst,
			swizzle_xxxx(srcreg(RC_FILE_TEMPORARY, tempreg)),
			constants);

		dst.WriteMask = inst->U.I.DstReg.WriteMask & RC_MASK_Y;
		sin_approx(c, inst, dst,
			swizzle_yyyy(srcreg(RC_FILE_TEMPORARY, tempreg)),
			constants);
	}

	rc_remove_instruction(inst);

	return 1;
}
コード例 #28
0
ファイル: radeon_program_alu.c プロジェクト: nikai3d/mesa
static void transform_SFL(struct radeon_compiler* c,
	struct rc_instruction* inst)
{
	emit1(c, inst->Prev, RC_OPCODE_MOV, inst->U.I.SaturateMode, inst->U.I.DstReg, builtin_zero);
	rc_remove_instruction(inst);
}