#define NO_MASK 0xf
-/** Returns the mask of channels read from the given src in this instruction, We
- * also provide one optional masks which may mask other components in the dst
- * register
+/**
+ * Returns the mask of channels (bitmask of WRITEMASK_X,Y,Z,W) which
+ * are read from the given src in this instruction, We also provide
+ * one optional masks which may mask other components in the dst
+ * register
*/
static GLuint
-get_src_arg_mask(const struct prog_instruction *inst, int arg, int dst_mask)
+get_src_arg_mask(const struct prog_instruction *inst,
+ GLuint arg, GLuint dst_mask)
{
- int read_mask, channel_mask;
- int comp;
+ GLuint read_mask, channel_mask;
+ GLuint comp;
+
ASSERT(arg < _mesa_num_inst_src_regs(inst->Opcode));
/* Form the dst register, find the written channels */
/* Now, given the src swizzle and the written channels, find which
* components are actually read
*/
- read_mask = 0;
+ read_mask = 0x0;
for (comp = 0; comp < 4; ++comp) {
- const int coord = GET_SWZ(inst->SrcReg[arg].Swizzle, comp);
+ const GLuint coord = GET_SWZ(inst->SrcReg[arg].Swizzle, comp);
ASSERT(coord < 4);
if (channel_mask & (1 << comp) && coord <= SWIZZLE_W)
read_mask |= 1 << coord;
return read_mask;
}
-/** For a MOV instruction, compute a write mask when src register also has
- * a mask
+
+/**
+ * For a MOV instruction, compute a write mask when src register also has
+ * a mask
*/
static GLuint
-get_dst_mask_for_mov(const struct prog_instruction *mov, int src_mask)
+get_dst_mask_for_mov(const struct prog_instruction *mov, GLuint src_mask)
{
- const int mask = mov->DstReg.WriteMask;
- int comp;
- int updated_mask = 0;
+ const GLuint mask = mov->DstReg.WriteMask;
+ GLuint comp;
+ GLuint updated_mask = 0x0;
+
ASSERT(mov->Opcode == OPCODE_MOV);
for (comp = 0; comp < 4; ++comp) {
- int src_comp;
+ GLuint src_comp;
if ((mask & (1 << comp)) == 0)
continue;
src_comp = GET_SWZ(mov->SrcReg[0].Swizzle, comp);
return updated_mask;
}
-/** Ensure that the swizzle is regular */
-static int
-is_swizzle_regular(int swz)
+
+/**
+ * Ensure that the swizzle is regular. That is, all of the swizzle
+ * terms are SWIZZLE_X,Y,Z,W and not SWIZZLE_ZERO or SWIZZLE_ONE.
+ */
+static GLboolean
+is_swizzle_regular(GLuint swz)
{
return GET_SWZ(swz,0) <= SWIZZLE_W &&
GET_SWZ(swz,1) <= SWIZZLE_W &&
GET_SWZ(swz,3) <= SWIZZLE_W;
}
+
/**
* In 'prog' remove instruction[i] if removeFlags[i] == TRUE.
* \return number of instructions removed
}
}
+
/**
* Remove dead instructions from the given program.
* This is very primitive for now. Basically look for temp registers
END
};
+
/**
* Scan forward in program from 'start' for the next occurances of TEMP[index].
* We look if an instruction reads the component given by the masks and if they
return END;
}
-static GLboolean _mesa_is_flow_control_opcode(enum prog_opcode opcode)
+
+/**
+ * Is the given instruction opcode a flow-control opcode?
+ * XXX maybe move this into prog_instruction.[ch]
+ */
+static GLboolean
+_mesa_is_flow_control_opcode(enum prog_opcode opcode)
{
switch (opcode) {
case OPCODE_BGNLOOP:
}
}
+
+/**
+ * Test if the given instruction is a simple MOV (no conditional updating,
+ * not relative addressing, no negation/abs, etc).
+ */
static GLboolean
can_downward_mov_be_modifed(const struct prog_instruction *mov)
{
mov->SaturateMode == SATURATE_OFF;
}
+
static GLboolean
can_upward_mov_be_modifed(const struct prog_instruction *mov)
{
mov->DstReg.File == PROGRAM_TEMPORARY;
}
+
/**
* Try to remove use of extraneous MOV instructions, to free them up for dead
* code removal.
for (i = 0; i + 1 < prog->NumInstructions; i++) {
const struct prog_instruction *mov = prog->Instructions + i;
- int dst_mask, src_mask;
+ GLuint dst_mask, src_mask;
if (can_upward_mov_be_modifed(mov) == GL_FALSE)
continue;
/* First rewrite this instruction's args if appropriate. */
for (arg = 0; arg < _mesa_num_inst_src_regs(inst2->Opcode); arg++) {
- int comp, read_mask;
+ GLuint comp, read_mask;
if (inst2->SrcReg[arg].File != mov->DstReg.File ||
inst2->SrcReg[arg].Index != mov->DstReg.Index ||
/* Adjust the swizzles of inst2 to point at MOV's source if ALL the
* components read still come from the mov instructions
*/
- if(is_swizzle_regular(inst2->SrcReg[arg].Swizzle) &&
+ if (is_swizzle_regular(inst2->SrcReg[arg].Swizzle) &&
(read_mask & dst_mask) == read_mask) {
for (comp = 0; comp < 4; comp++) {
- int inst2_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp);
-
- GLuint s = GET_SWZ(mov->SrcReg[0].Swizzle, inst2_swz);
+ const GLuint inst2_swz =
+ GET_SWZ(inst2->SrcReg[arg].Swizzle, comp);
+ const GLuint s = GET_SWZ(mov->SrcReg[0].Swizzle, inst2_swz);
inst2->SrcReg[arg].Swizzle &= ~(7 << (3 * comp));
inst2->SrcReg[arg].Swizzle |= s << (3 * comp);
inst2->SrcReg[arg].Negate ^= (((mov->SrcReg[0].Negate >>
}
}
+
/**
* Complements dead_code_global. Try to remove code in block of code by
* carefully monitoring the swizzles. Both functions should be merged into one
return rem != 0;
}
+
/**
* Try to inject the destination of mov as the destination of inst and recompute
* the swizzles operators for the sources of inst if required. Return GL_TRUE
case OPCODE_MUL:
case OPCODE_SUB:
{
- int dst_to_src_comp[4] = {0,0,0,0};
- int dst_comp, arg;
+ GLuint dst_to_src_comp[4] = {0,0,0,0};
+ GLuint dst_comp, arg;
for (dst_comp = 0; dst_comp < 4; ++dst_comp) {
if (mov->DstReg.WriteMask & (1 << dst_comp)) {
- const int src_comp = GET_SWZ(mov->SrcReg[0].Swizzle, dst_comp);
+ const GLuint src_comp = GET_SWZ(mov->SrcReg[0].Swizzle, dst_comp);
ASSERT(src_comp < 4);
dst_to_src_comp[dst_comp] = src_comp;
}
/* Patch each source of the instruction */
for (arg = 0; arg < _mesa_num_inst_src_regs(inst->Opcode); arg++) {
- const int arg_swz = inst->SrcReg[arg].Swizzle;
+ const GLuint arg_swz = inst->SrcReg[arg].Swizzle;
inst->SrcReg[arg].Swizzle = 0;
/* Reset each active component of the swizzle */
for (dst_comp = 0; dst_comp < 4; ++dst_comp) {
- int src_comp, arg_comp;
+ GLuint src_comp, arg_comp;
if ((mov->DstReg.WriteMask & (1 << dst_comp)) == 0)
continue;
src_comp = dst_to_src_comp[dst_comp];
}
}
+
/**
* Try to remove extraneous MOV instructions from the given program.
*/
return 0;
}
+
/** sort the interval list according to interval starts */
static void
sort_interval_list_by_start(struct interval_list *list)
}
}
+
#if 0
static void
print_it(GLcontext *ctx, struct gl_program *program, const char *txt) {
}
#endif
+
/**
* Apply optimizations to the given program to eliminate unnecessary
* instructions, temp regs, etc.