Use IR_LOOP to represent do-while and for-loops.
authorBrian <brian@nostromo.localnet.net>
Wed, 7 Feb 2007 22:12:13 +0000 (15:12 -0700)
committerBrian <brian@nostromo.localnet.net>
Wed, 7 Feb 2007 22:12:13 +0000 (15:12 -0700)
Also, start moving high vs. low-level instruction selection into slang_emit.c

src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h
src/mesa/shader/slang/slang_link.c
src/mesa/swrast/s_fragprog.c

index 42c1f0897eb334a3ec4c44fc005b18976dff45d4..14870f57ae8ba601cf5c6c69a35b5ba46b2b326d 100644 (file)
@@ -1423,7 +1423,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
 
 
 /**
- * Generate IR tree for a while-loop using high-level LOOP, IF instructions.
+ * Generate loop code using high-level IR_LOOP instruction
  */
 static slang_ir_node *
 _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
@@ -1509,6 +1509,46 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
 }
 
 
+/**
+ * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
+ */
+static slang_ir_node *
+_slang_gen_hl_do(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   slang_ir_node *prevLoop;
+   /*
+    * LOOP:
+    *    body code (child[0])
+    *    eval expr (child[1]), updating condcodes
+    *    IF !expr:
+    *       BRK
+    */
+   slang_ir_node *ifThen, *cond, *body, *loop;
+
+   loop = new_loop(NULL);
+
+   /* save old, push new loop */
+   prevLoop = A->CurLoop;
+   A->CurLoop = loop;
+
+   body = _slang_gen_operation(A, &oper->children[0]);
+
+   cond = _slang_gen_operation(A, &oper->children[1]);
+   cond = new_node1(IR_NOT, cond);
+   cond = _slang_gen_cond(cond);
+
+   ifThen = new_if(cond,
+                   new_break(A->CurLoop),
+                   NULL);
+
+   loop->Children[0] = new_seq(body, ifThen);
+
+   A->CurLoop = prevLoop; /* pop loop, restore prev */
+
+   return loop;
+}
+
+
 /**
  * Generate IR tree for a for-loop.
  */
@@ -1573,69 +1613,48 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
 
 
 /**
- * Generate IR tree for a for-loop, using high-level BGNLOOP/ENDLOOP and
- * IF/ENDIF instructions.
- *
- * XXX note done yet!
+ * Generate for-loop using high-level IR_LOOP instruction.
  */
 static slang_ir_node *
 _slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
 {
+   slang_ir_node *prevLoop;
    /*
-    * init code (child[0])
-    * BGNLOOP
+    * init (child[0])
+    * LOOP:
     *    eval expr (child[1]), updating condcodes
-    *    IF !expr THEN
+    *    IF !expr:
     *       BRK
-    *    ENDIF
-    *    code body (child[3])
-    *    label "__continueFor"   // jump here for "continue"
-    *    incr code (child[2])
-    * ENDLOOP
+    *    body code (child[3])
+    *    incr code (child[2])   // XXX continue here
     */
-   slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
-   slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
-   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
-   slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
-   slang_ir_node *incr, *jump, *endLab, *tree;
-   slang_atom prevLoopBreak = A->CurLoopBreak;
-   slang_atom prevLoopCont = A->CurLoopCont;
-
-   /* Push this loop */
-   A->CurLoopBreak = endAtom;
-   A->CurLoopCont = contAtom;
+   slang_ir_node *init, *ifThen, *cond, *body, *loop, *incr;
 
    init = _slang_gen_operation(A, &oper->children[0]);
-   startLab = new_label(startAtom);
-   tree = new_seq(init, startLab);
+   loop = new_loop(NULL);
+
+   /* save old, push new loop */
+   prevLoop = A->CurLoop;
+   A->CurLoop = loop;
 
    cond = _slang_gen_operation(A, &oper->children[1]);
+   cond = new_node1(IR_NOT, cond);
    cond = _slang_gen_cond(cond);
-   tree = new_seq(tree, cond);
 
-   bra = new_cjump(endAtom, 0);
-   tree = new_seq(tree, bra);
+   ifThen = new_if(cond,
+                   new_break(A->CurLoop),
+                   NULL);
 
    body = _slang_gen_operation(A, &oper->children[3]);
-   tree = new_seq(tree, body);
-
-   contLab = new_label(contAtom);
-   tree = new_seq(tree, contLab);
 
    incr = _slang_gen_operation(A, &oper->children[2]);
-   tree = new_seq(tree, incr);
-
-   jump = new_jump(startAtom);
-   tree = new_seq(tree, jump);
 
-   endLab = new_label(endAtom);
-   tree = new_seq(tree, endLab);
+   loop->Children[0] = new_seq(ifThen,
+                               new_seq(body,incr));
 
-   /* Pop this loop */
-   A->CurLoopBreak = prevLoopBreak;
-   A->CurLoopCont = prevLoopCont;
+   A->CurLoop = prevLoop; /* pop loop, restore prev */
 
-   return tree;
+   return new_seq(init, loop);
 }
 
 
@@ -2434,7 +2453,10 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
       else
          return _slang_gen_while(A, oper);
    case slang_oper_do:
-      return _slang_gen_do(A, oper);
+      if (UseHighLevelInstructions)
+         return _slang_gen_hl_do(A, oper);
+      else
+         return _slang_gen_do(A, oper);
    case slang_oper_for:
       if (UseHighLevelInstructions)
          return _slang_gen_hl_for(A, oper);
index 2d5a7cf6f9da82f21c029b853a965ae6bad92784..29588379a2f10a0e265d2e4a6477884530f5eb08 100644 (file)
@@ -43,6 +43,9 @@
 #define ANNOTATE 1
 
 
+static GLboolean EmitHighLevelInstructions = GL_FALSE;
+
+
 /**
  * Assembly and IR info
  */
@@ -1304,57 +1307,72 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
    case IR_LOOP:
       {
          struct prog_instruction *beginInst, *endInst;
-         GLuint endInstLoc;
-         slang_ir_node *p;
+         GLuint beginInstLoc, endInstLoc;
+         slang_ir_node *ir;
 
-         /* save location of this instruction, used by OPCODE_ENDLOOP */
-         n->InstLocation = prog->NumInstructions;
-         (void) new_instruction(prog, OPCODE_BGNLOOP);
+         /* emit OPCODE_BGNLOOP */
+         beginInstLoc = prog->NumInstructions;
+         if (EmitHighLevelInstructions) {
+            (void) new_instruction(prog, OPCODE_BGNLOOP);
+         }
 
          /* body */
          emit(vt, n->Children[0], prog);
 
          endInstLoc = prog->NumInstructions;
-         endInst = new_instruction(prog, OPCODE_ENDLOOP);
-         /* The ENDLOOP's BranchTarget points to top of loop */
-         endInst->BranchTarget = n->InstLocation;
-         /* Update BGNLOOP's BranchTarget to point to this instruction */
-         beginInst = prog->Instructions + n->InstLocation;
-         beginInst->BranchTarget = prog->NumInstructions - 1;
+         if (EmitHighLevelInstructions) {
+            /* emit OPCODE_ENDLOOP */
+            endInst = new_instruction(prog, OPCODE_ENDLOOP);
+         }
+         else {
+            /* emit unconditional BRA-nch */
+            endInst = new_instruction(prog, OPCODE_BRA);
+            endInst->DstReg.CondMask = COND_TR;  /* always true */
+         }
+         /* end instruction's BranchTarget points to top of loop */
+         endInst->BranchTarget = beginInstLoc;
+
+         if (EmitHighLevelInstructions) {
+            /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+            beginInst = prog->Instructions + beginInstLoc;
+            beginInst->BranchTarget = prog->NumInstructions - 1;
+         }
 
          /* Done emitting loop code.  Now walk over the loop's linked list
-          * of BREAK and CONT nodes, filling in their BranchTarget fields.
+          * of BREAK and CONT nodes, filling in their BranchTarget fields
+          * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
           */
-         for (p = n->BranchNode; p; p = p->BranchNode) {
-            if (p->Opcode == IR_BREAK) {
-               struct prog_instruction *brkInst
-                  = prog->Instructions + p->InstLocation;
-               assert(brkInst->Opcode == OPCODE_BRK);
-               brkInst->BranchTarget = endInstLoc + 1;
+         for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
+            struct prog_instruction *inst
+               = prog->Instructions + ir->InstLocation;
+            if (ir->Opcode == IR_BREAK) {
+               assert(inst->Opcode == OPCODE_BRK ||
+                      inst->Opcode == OPCODE_BRA);
+               inst->BranchTarget = endInstLoc + 1;
             }
             else {
-               assert(p->Opcode == IR_CONT);
-               struct prog_instruction *contInst
-                  = prog->Instructions + p->InstLocation;
-               assert(contInst->Opcode == OPCODE_CONT);
-               contInst->BranchTarget = endInstLoc;
+               assert(ir->Opcode == IR_CONT);
+               assert(inst->Opcode == OPCODE_CONT ||
+                      inst->Opcode == OPCODE_BRA);
+               inst->BranchTarget = endInstLoc;
             }
          }
          return NULL;
       }
-   case IR_CONT:
-      {
-         struct prog_instruction *inst;
-         n->InstLocation = prog->NumInstructions;
-         inst = new_instruction(prog, OPCODE_CONT);
-         inst->DstReg.CondMask = COND_TR;  /* always true */
-         return inst;
-      }
    case IR_BREAK:
+      /* fall-through */
+   case IR_CONT:
       {
+         gl_inst_opcode opcode;
          struct prog_instruction *inst;
          n->InstLocation = prog->NumInstructions;
-         inst = new_instruction(prog, OPCODE_BRK);
+         if (EmitHighLevelInstructions) {
+            opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+         }
+         else {
+            opcode = OPCODE_BRA;
+         }
+         inst = new_instruction(prog, opcode);
          inst->DstReg.CondMask = COND_TR;  /* always true */
          return inst;
       }
index a7c858c69f748093aef572a6e1aaf60e7ee0c409..0c827d9cd8ce6560a60f81cb38fd24c0161f5e09 100644 (file)
@@ -39,7 +39,7 @@
 
 
 /**
- * Intermediate Representation opcode
+ * Intermediate Representation opcodes
  */
 typedef enum
 {
@@ -64,6 +64,11 @@ typedef enum
    IR_CONT,      /* continue loop */
    IR_BREAK,     /* break loop */
 
+   IR_BREAK_IF_TRUE,
+   IR_BREAK_IF_FALSE,
+   IR_CONT_IF_TRUE,
+   IR_CONT_IF_FALSE,
+
    IR_MOVE,
    IR_ADD,
    IR_SUB,
index 017cf6078cbcb4cd3a2b128883dc3527973c8453..b1d355ff80255c58ed2d8273d63924f0cc570312 100644 (file)
@@ -298,7 +298,7 @@ _slang_resolve_branches(struct gl_program *prog)
 
    for (i = 0; i < prog->NumInstructions; i++) {
       struct prog_instruction *inst = prog->Instructions + i;
-      if (inst->Opcode == OPCODE_BRA) {
+      if (inst->Opcode == OPCODE_BRA && inst->BranchTarget < 0) {
          for (j = 0; j < numTargets; j++) {
             if (!strcmp(inst->Comment, targets[j].Name)) {
                inst->BranchTarget = targets[j].Pos;
index 403a03aa32aecc544191c5f6f5672e2b9a150375..ace10a9222c59517155d6df996e4fd20592f43cf 100644 (file)
@@ -675,9 +675,10 @@ execute_program( GLcontext *ctx,
                }
             }
             break;
-         case OPCODE_BGNLOOP: /* begin loop */
+         case OPCODE_BGNLOOP:
+            /* no-op */
             break;
-         case OPCODE_ENDLOOP: /* end loop */
+         case OPCODE_ENDLOOP:
             /* subtract 1 here since pc is incremented by for(pc) loop */
             pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */
             break;
@@ -695,10 +696,7 @@ execute_program( GLcontext *ctx,
                    test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
                    test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
                   /* take branch */
-                  pc = inst->BranchTarget;
-                  /*
-                  printf("Take branch to %u\n", pc);
-                  */
+                  pc = inst->BranchTarget - 1;
                }
             }
             break;
@@ -721,7 +719,7 @@ execute_program( GLcontext *ctx,
                      return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
                   }
                   machine->CallStack[machine->StackDepth++] = pc + 1;
-                  pc = inst->BranchTarget;
+                  pc = inst->BranchTarget; /* XXX - 1 ??? */
                }
             }
             break;