asahi: Use extr instruction for txs lowering
AGX has an instruction extr
which extracts a bitfield from a pair of 32-bit registers.
Pseudo-code from Dougall's documentation of the instruction set:
D = ALUDst(Dx:D, Dt)
A = ALUSrc(Ax:A, At)
B = ALUSrc(Bx:B, Bt)
C = ALUSrc(Cx:C, Ct)
m = m3:m2:m1
for each active thread:
a = A[thread]
b = B[thread]
c = C[thread]
shift_amount = (c & 0x7F)
if m == 0:
mask = 0xFFFFFFFF
else:
mask = (1 << m) - 1
result = (((b << 32) | a) >> shift_amount) & mask
D[thread] = result
This instruction would be useful in src/asahi/compiler/agx_lower_resinfo.c
to extract the "width" from a texture descriptor. Currently, that code generates a bunch of bitwise arithmetic in NIR for the task:
/* Width minus 1: bits [28, 42) */
nir_ssa_def *width_m1 = nir_ior(b, nir_ushr_imm(b, w0, 28),
nir_ishl_imm(b, nir_iand_imm(b, w1,
BITFIELD_MASK(14 - 4)), 4));
However, this could be done with a single instruction:
extr width_m1, w0, w1, 28, m=14
In this task, you should:
-
Add a vendored NIR instruction extr_agx
mapping to this opcode (mesa/src/compiler/nir/nir_opcodes.py
), paraphrasing the above text as justification. The NIR instruction will take 4 sources (a, b, c, m). You will need to write a C expression mapping to the instruction behaviour, you can get that from the pseudocode. Add comments explaining the high level behaviour. -
Change the quoted code to use nir_extr_agx
instead (src/asahi/compiler/agx_lower_resinfo.c
) -
Add the extr
instruction to the compiler's intermediate representation (src/asahi/compiler/agx_opcodes.py
) -
Add any necessary changes to instruction packing to handle the new instruction ( src/asahi/compiler/agx_pack.c
) -
Translate nir_op_extr_agx
toextr
in backend instruction selection (src/asahi/compiler/agx_compile.c
functionagx_emit_alu
)