i965: Jump to the end of the next outer conditional block on ENDIFs.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 12 Dec 2012 10:20:05 +0000 (02:20 -0800)
committerEric Anholt <eric@anholt.net>
Fri, 14 Dec 2012 23:42:34 +0000 (15:42 -0800)
From the Ivybridge PRM, Volume 4, Part 3, section 6.24 (page 172):

"The endif instruction is also used to hop out of nested conditionals by
 jumping to the end of the next outer conditional block when all
 channels are disabled."

Also:
"Pseudocode:
 Evaluate(WrEn);
 if ( WrEn == 0 ) {  // all channels false
   Jump(IP + JIP);
 }"

First, ENDIF re-enables any channels that were disabled because they
didn't match the conditional.  If any channels are active, it proceeds
to the next instruction (IP + 16).  However, if they're all disabled,
there's no point in walking through all of the instructions that have no
effect---it can jump to the next instruction that might re-enable some
channels (an ELSE, ENDIF, or WHILE).

Previously, we always set JIP on ENDIF instructions to 2 (which is
measured in 8-byte units).  This made it do Jump(IP + 16), which just
meant it would go to the next instruction even if all channels were off.

It turns out that walking over instructions while all the channels are
disabled like this is worse than just instruction dispatch overhead: if
there are texturing messages, it still costs a couple hundred cycles to
not-actually-read from the texture results.

This patch finds the next instruction that could re-enable channels and
sets JIP accordingly.

Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_eu_emit.c

index dd91a3087c8151af47f14deaa7c59d43b2b12fe8..c294bae74d9a05cc017f629068ab7a3ae98d5545 100644 (file)
@@ -2396,7 +2396,14 @@ brw_set_uip_jip(struct brw_compile *p)
 
         assert(insn->bits3.break_cont.uip != 0);
         assert(insn->bits3.break_cont.jip != 0);
+
+      case BRW_OPCODE_ENDIF:
+         if (block_end_ip == 0)
+            insn->bits3.break_cont.jip = 2;
+         else
+            insn->bits3.break_cont.jip = (block_end_ip - ip) / scale;
         break;
+
       case BRW_OPCODE_HALT:
         /* From the Sandy Bridge PRM (volume 4, part 2, section 8.3.19):
          *