From 2288ef916cfad6d65a55f66cde057f83da2b2692 Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Tue, 5 Mar 2024 15:00:28 +0100 Subject: [PATCH] ir3: model predt/predf without sources We used to model predt/predf as taking a predicate register source. The blob disassembler shows them taking a label argument. However, it seems that both are incorrect: the condition is always taken from p0.x and I have not been able to construct a test case were the label makes any difference. This patch changes predt/predf to not take any arguments and adds documentation about how predicated execution works. Signed-off-by: Job Noorman Part-of: --- src/freedreno/ir3/ir3_parser.y | 4 +-- src/freedreno/ir3/tests/disasm.c | 4 +-- src/freedreno/isa/ir3-cat0.xml | 48 +++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index f16fe903432..7b69bf530d4 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -901,8 +901,8 @@ cat0_instr: T_OP_NOP { new_instr(OPC_NOP); } | T_OP_DBG { new_instr(OPC_DBG); } | T_OP_SHPS { new_instr(OPC_SHPS); } cat0_immed | T_OP_SHPE { new_instr(OPC_SHPE); } -| T_OP_PREDT { new_instr(OPC_PREDT); } cat0_src1 -| T_OP_PREDF { new_instr(OPC_PREDF); } cat0_src1 +| T_OP_PREDT { new_instr(OPC_PREDT); } +| T_OP_PREDF { new_instr(OPC_PREDF); } | T_OP_PREDE { new_instr(OPC_PREDE); } | T_OP_GETLAST '.' T_W { new_instr(OPC_GETLAST); } cat0_immed diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index 63eec55e9d6..0a8ed52d401 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -78,8 +78,8 @@ static const struct test { INSTR_6XX(00804040_00000003, "braa p0.x, p0.y, #3"), INSTR_6XX(07820000_00000000, "prede"), INSTR_6XX(00800063_0000001e, "brac.3 #30"), - INSTR_6XX(06820000_00000000, "predt p0.x"), - INSTR_6XX(07020000_00000000, "predf p0.x"), + INSTR_6XX(06820000_00000000, "predt"), + INSTR_6XX(07020000_00000000, "predf"), INSTR_6XX(07820000_00000000, "prede"), /* cat1 */ diff --git a/src/freedreno/isa/ir3-cat0.xml b/src/freedreno/isa/ir3-cat0.xml index 03bf7f37759..a5e778650db 100644 --- a/src/freedreno/isa/ir3-cat0.xml +++ b/src/freedreno/isa/ir3-cat0.xml @@ -110,6 +110,44 @@ SOFTWARE. 1000 + + + The predt, predf, and prede instructions are used to enable + "predicated execution" for a region of code. During predicated + execution, the execution mask is combined with the "predication + mask" to determine the active fibers. So this is similar to + branching with the exception that inactive fibers keep executing + instead of being parked; the instructions they execute simply + have no effect. Since no branch stack is necessary to support + predication, it is more performant for divergent branches. + + More concretely, the hardware seems to keep track of a + predication mask and a predication mode. The mode can be "none" + (no predication, the default, and set by prede), "true" (set by + predt), or "false" (set by predf). The final execution mask is + determined by and'ing with ~0 (none mode), the predication mask + (true mode), or its negation (false mode). + + Predication is enabled by predt or predf which take the value of + p0.x of all fibers (not only the active ones) and store them in + the predication mask. Then the mode is set to true or false. + Executing prede disables predication by setting the mode to + none. + + One peculiarity, and the reason the execution mode state is + necessary, is that any instruction marked with (jp) will also + update the execution mask. The current mode will be kept in that + case. + + xx1 + 1101 + + + + xx1 + 1110 + + xx1 1111 @@ -136,16 +174,6 @@ SOFTWARE. 0101 - - xx1 - 1101 - - - - xx1 - 1110 - -