freedreno/ir3: cleanup double cmps.s from frontend
Since we cannot mov into a predicate register, the frontend uses a 'cmps.s p0.x, cond, 0' as a stand-in for mov to p0.x. It does this since it has no way to know that the source cond instruction (ie. for a kill, br, etc) will only be used to write the predicate reg. Detect this, and re-write the instruction writing p0.x to skip the original cmps.[sfu]. (It is done like this, rather than re-writing the dest of the first cmps.[sfu] in case the first cmps.[sfu] actually has other users.) Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
parent
9bac27dbf9
commit
b35ad6e701
|
@ -442,6 +442,37 @@ instr_cp(struct ir3_instruction *instr)
|
|||
instr_cp(instr->address);
|
||||
ir3_instr_set_address(instr, eliminate_output_mov(instr->address));
|
||||
}
|
||||
|
||||
/* we can end up with extra cmps.s from frontend, which uses a
|
||||
*
|
||||
* cmps.s p0.x, cond, 0
|
||||
*
|
||||
* as a way to mov into the predicate register. But frequently 'cond'
|
||||
* is itself a cmps.s/cmps.f/cmps.u. So detect this special case and
|
||||
* just re-write the instruction writing predicate register to get rid
|
||||
* of the double cmps.
|
||||
*/
|
||||
if ((instr->opc == OPC_CMPS_S) &&
|
||||
(instr->regs[0]->num == regid(REG_P0, 0)) &&
|
||||
ssa(instr->regs[1]) &&
|
||||
(instr->regs[2]->flags & IR3_REG_IMMED) &&
|
||||
(instr->regs[2]->iim_val == 0)) {
|
||||
struct ir3_instruction *cond = ssa(instr->regs[1]);
|
||||
switch (cond->opc) {
|
||||
case OPC_CMPS_S:
|
||||
case OPC_CMPS_F:
|
||||
case OPC_CMPS_U:
|
||||
instr->opc = cond->opc;
|
||||
instr->flags = cond->flags;
|
||||
instr->cat2 = cond->cat2;
|
||||
instr->address = cond->address;
|
||||
instr->regs[1] = cond->regs[1];
|
||||
instr->regs[2] = cond->regs[2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue