r600g: optimize away CF_INST_POP
authorChristian König <deathsimple@vodafone.de>
Mon, 13 Dec 2010 23:43:53 +0000 (00:43 +0100)
committerChristian König <deathsimple@vodafone.de>
Mon, 13 Dec 2010 23:43:53 +0000 (00:43 +0100)
If last instruction is an CF_INST_ALU we don't need to emit an
additional CF_INST_POP for stack clean up after an IF ELSE ENDIF.

src/gallium/drivers/r600/r600_asm.c
src/gallium/drivers/r600/r600_shader.c

index 1f41269534a381cb496c8c5a67b36e594bfb559f..4476f432b98227a09bffff25ab9f740e20b831fa 100644 (file)
@@ -507,6 +507,8 @@ int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
        }
        /* same on EG */
        if (((bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3)) &&
+            (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3)) &&
+            (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3)) &&
             (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3))) ||
                LIST_IS_EMPTY(&bc->cf_last->alu)) {
                R600_ERR("last CF is not ALU (%p)\n", bc->cf_last);
@@ -728,6 +730,8 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
 
        switch (cf->inst) {
        case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+       case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3):
+       case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3):
        case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3):
                bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1) |
                        S_SQ_CF_ALU_WORD0_KCACHE_MODE0(cf->kcache0_mode) |
@@ -808,6 +812,8 @@ int r600_bc_build(struct r600_bc *bc)
        LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
                switch (cf->inst) {
                case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+               case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3):
+               case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3):
                case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3):
                        break;
                case V_SQ_CF_WORD1_SQ_CF_INST_TEX:
@@ -854,6 +860,8 @@ int r600_bc_build(struct r600_bc *bc)
                        return r;
                switch (cf->inst) {
                case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+               case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3):
+               case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3):
                case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3):
                        LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) {
                                switch(bc->chiprev) {
index 6cf235355151db258db29ab198eb36d335313da6..aaebd16a3102a441f210abab1dd2123c959ea4c8 100644 (file)
@@ -2676,9 +2676,25 @@ static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode)
 
 static int pops(struct r600_shader_ctx *ctx, int pops)
 {
-       r600_bc_add_cfinst(ctx->bc, CTX_INST(V_SQ_CF_WORD1_SQ_CF_INST_POP));
-       ctx->bc->cf_last->pop_count = pops;
-       ctx->bc->cf_last->cf_addr = ctx->bc->cf_last->id + 2;
+       int alu_pop = 3;
+       if (ctx->bc->cf_last) {
+               if (ctx->bc->cf_last->inst == CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU) << 3)
+                       alu_pop = 0;
+               else if (ctx->bc->cf_last->inst == CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER) << 3)
+                       alu_pop = 1;
+       }
+       alu_pop += pops;
+       if (alu_pop == 1) {
+               ctx->bc->cf_last->inst = CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER) << 3;
+               ctx->bc->force_add_cf = 1;
+       } else if (alu_pop == 2) {
+               ctx->bc->cf_last->inst = CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER) << 3;
+               ctx->bc->force_add_cf = 1;
+       } else {
+               r600_bc_add_cfinst(ctx->bc, CTX_INST(V_SQ_CF_WORD1_SQ_CF_INST_POP));
+               ctx->bc->cf_last->pop_count = pops;
+               ctx->bc->cf_last->cf_addr = ctx->bc->cf_last->id + 2;
+       }
        return 0;
 }