diff --git a/src/gallium/drivers/r300/compiler/radeon_program_alu.c b/src/gallium/drivers/r300/compiler/radeon_program_alu.c index 5d76e5b6b97..5e32e7b1fd0 100644 --- a/src/gallium/drivers/r300/compiler/radeon_program_alu.c +++ b/src/gallium/drivers/r300/compiler/radeon_program_alu.c @@ -294,12 +294,30 @@ static void transform_TRUNC(struct radeon_compiler* c, * The multiplication by sgn(x) can be simplified using CMP: * y * sgn(x) = (x < 0 ? -y : y) */ + + struct rc_src_register abs; + + if (c->is_r500) { + abs = absolute(inst->U.I.SrcReg[0]); + } else { + /* abs isn't free on r300/r400, so we want + * to avoid doing it twice + */ + int tmp = rc_find_free_temporary(c); + + emit2(c, inst->Prev, RC_OPCODE_MAX, NULL, dstregtmpmask(tmp, RC_MASK_XYZW), + srcregswz(inst->U.I.SrcReg[0].File, inst->U.I.SrcReg[0].Index, RC_SWIZZLE_XYZW), + negate(srcregswz(inst->U.I.SrcReg[0].File, inst->U.I.SrcReg[0].Index, RC_SWIZZLE_XYZW))); + abs = srcregswz(RC_FILE_TEMPORARY, tmp, inst->U.I.SrcReg[0].Swizzle); + + } struct rc_dst_register dst = try_to_reuse_dst(c, inst); - emit1(c, inst->Prev, RC_OPCODE_FRC, NULL, dst, absolute(inst->U.I.SrcReg[0])); - emit2(c, inst->Prev, RC_OPCODE_ADD, NULL, dst, absolute(inst->U.I.SrcReg[0]), + emit1(c, inst->Prev, RC_OPCODE_FRC, NULL, dst, abs); + emit2(c, inst->Prev, RC_OPCODE_ADD, NULL, dst, abs, 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); }