radeonsi/gfx10: fix the vertex order for triangle strips emitted by a GS
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_flow.c
index 5bc9c741a884a6134ac0bdde674fd08dfb213cf2..3bd24b4ba875b3d6a6df7b966e1122316a6fd4c2 100644 (file)
 #include "util/u_debug.h"
 #include "util/u_memory.h"
 
+#include "lp_bld_init.h"
 #include "lp_bld_type.h"
 #include "lp_bld_flow.h"
 
 
-#define LP_BUILD_FLOW_MAX_VARIABLES 64
-#define LP_BUILD_FLOW_MAX_DEPTH 32
-
-/**
- * Enumeration of all possible flow constructs.
- */
-enum lp_build_flow_construct_kind {
-   LP_BUILD_FLOW_SCOPE,
-   LP_BUILD_FLOW_SKIP,
-   LP_BUILD_FLOW_IF
-};
-
-
-/**
- * Variable declaration scope.
- */
-struct lp_build_flow_scope
-{
-   /** Number of variables declared in this scope */
-   unsigned num_variables;
-};
-
-
-/**
- * Early exit. Useful to skip to the end of a function or block when
- * the execution mask becomes zero or when there is an error condition.
- */
-struct lp_build_flow_skip
-{
-   /** Block to skip to */
-   LLVMBasicBlockRef block;
-
-   /** Number of variables declared at the beginning */
-   unsigned num_variables;
-
-   LLVMValueRef *phi;  /**< array [num_variables] */
-};
-
-
-/**
- * if/else/endif.
- */
-struct lp_build_flow_if
-{
-   unsigned num_variables;
-
-   LLVMValueRef *phi;  /**< array [num_variables] */
-
-   LLVMValueRef condition;
-   LLVMBasicBlockRef entry_block, true_block, false_block, merge_block;
-};
-
-
-/**
- * Union of all possible flow constructs' data
- */
-union lp_build_flow_construct_data
-{
-   struct lp_build_flow_scope scope;
-   struct lp_build_flow_skip skip;
-   struct lp_build_flow_if ifthen;
-};
-
-
-/**
- * Element of the flow construct stack.
- */
-struct lp_build_flow_construct
-{
-   enum lp_build_flow_construct_kind kind;
-   union lp_build_flow_construct_data data;
-};
-
-
 /**
- * All necessary data to generate LLVM control flow constructs.
+ * Insert a new block, right where builder is pointing to.
  *
- * Besides keeping track of the control flow construct themselves we also
- * need to keep track of variables in order to generate SSA Phi values.
- */
-struct lp_build_flow_context
-{
-   LLVMBuilderRef builder;
-
-   /**
-    * Control flow stack.
-    */
-   struct lp_build_flow_construct constructs[LP_BUILD_FLOW_MAX_DEPTH];
-   unsigned num_constructs;
-
-   /**
-    * Variable stack
-    */
-   LLVMValueRef *variables[LP_BUILD_FLOW_MAX_VARIABLES];
-   unsigned num_variables;
-};
-
-
-struct lp_build_flow_context *
-lp_build_flow_create(LLVMBuilderRef builder)
-{
-   struct lp_build_flow_context *flow;
-
-   flow = CALLOC_STRUCT(lp_build_flow_context);
-   if(!flow)
-      return NULL;
-
-   flow->builder = builder;
-
-   return flow;
-}
-
-
-void
-lp_build_flow_destroy(struct lp_build_flow_context *flow)
-{
-   assert(flow->num_constructs == 0);
-   assert(flow->num_variables == 0);
-   FREE(flow);
-}
-
-
-/**
- * Begin/push a new flow control construct, such as a loop, skip block
- * or variable scope.
- */
-static union lp_build_flow_construct_data *
-lp_build_flow_push(struct lp_build_flow_context *flow,
-                   enum lp_build_flow_construct_kind kind)
-{
-   assert(flow->num_constructs < LP_BUILD_FLOW_MAX_DEPTH);
-   if(flow->num_constructs >= LP_BUILD_FLOW_MAX_DEPTH)
-      return NULL;
-
-   flow->constructs[flow->num_constructs].kind = kind;
-   return &flow->constructs[flow->num_constructs++].data;
-}
-
-
-/**
- * Return the current/top flow control construct on the stack.
- * \param kind  the expected type of the top-most construct
- */
-static union lp_build_flow_construct_data *
-lp_build_flow_peek(struct lp_build_flow_context *flow,
-                   enum lp_build_flow_construct_kind kind)
-{
-   assert(flow->num_constructs);
-   if(!flow->num_constructs)
-      return NULL;
-
-   assert(flow->constructs[flow->num_constructs - 1].kind == kind);
-   if(flow->constructs[flow->num_constructs - 1].kind != kind)
-      return NULL;
-
-   return &flow->constructs[flow->num_constructs - 1].data;
-}
-
-
-/**
- * End/pop the current/top flow control construct on the stack.
- * \param kind  the expected type of the top-most construct
- */
-static union lp_build_flow_construct_data *
-lp_build_flow_pop(struct lp_build_flow_context *flow,
-                  enum lp_build_flow_construct_kind kind)
-{
-   assert(flow->num_constructs);
-   if(!flow->num_constructs)
-      return NULL;
-
-   assert(flow->constructs[flow->num_constructs - 1].kind == kind);
-   if(flow->constructs[flow->num_constructs - 1].kind != kind)
-      return NULL;
-
-   return &flow->constructs[--flow->num_constructs].data;
-}
-
-
-/**
- * Begin a variable scope.
- *
- *
- */
-void
-lp_build_flow_scope_begin(struct lp_build_flow_context *flow)
-{
-   struct lp_build_flow_scope *scope;
-
-   scope = &lp_build_flow_push(flow, LP_BUILD_FLOW_SCOPE)->scope;
-   if(!scope)
-      return;
-
-   scope->num_variables = 0;
-}
-
-
-/**
- * Declare a variable.
- *
- * A variable is a named entity which can have different LLVMValueRef's at
- * different points of the program. This is relevant for control flow because
- * when there are multiple branches to a same location we need to replace
- * the variable's value with a Phi function as explained in
- * http://en.wikipedia.org/wiki/Static_single_assignment_form .
- *
- * We keep track of variables by keeping around a pointer to where they're
- * current.
- *
- * There are a few cautions to observe:
- *
- * - Variable's value must not be NULL. If there is no initial value then
- *   LLVMGetUndef() should be used.
- *
- * - Variable's value must be kept up-to-date. If the variable is going to be
- *   modified by a function then a pointer should be passed so that its value
- *   is accurate. Failure to do this will cause some of the variables'
- *   transient values to be lost, leading to wrong results.
+ * This is useful important not only for aesthetic reasons, but also for
+ * performance reasons, as frequently run blocks should be laid out next to
+ * each other and fall-throughs maximized.
  *
- * - A program should be written from top to bottom, by always appending
- *   instructions to the bottom with a single LLVMBuilderRef. Inserting and/or
- *   modifying existing statements will most likely lead to wrong results.
+ * See also llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp.
  *
- */
-void
-lp_build_flow_scope_declare(struct lp_build_flow_context *flow,
-                            LLVMValueRef *variable)
-{
-   struct lp_build_flow_scope *scope;
-
-   scope = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SCOPE)->scope;
-   if(!scope)
-      return;
-
-   assert(*variable);
-   if(!*variable)
-      return;
-
-   assert(flow->num_variables < LP_BUILD_FLOW_MAX_VARIABLES);
-   if(flow->num_variables >= LP_BUILD_FLOW_MAX_VARIABLES)
-      return;
-
-   flow->variables[flow->num_variables++] = variable;
-   ++scope->num_variables;
-}
-
-
-void
-lp_build_flow_scope_end(struct lp_build_flow_context *flow)
-{
-   struct lp_build_flow_scope *scope;
-
-   scope = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SCOPE)->scope;
-   if(!scope)
-      return;
-
-   assert(flow->num_variables >= scope->num_variables);
-   if(flow->num_variables < scope->num_variables) {
-      flow->num_variables = 0;
-      return;
-   }
-
-   flow->num_variables -= scope->num_variables;
-}
-
-
-/**
  * Note: this function has no dependencies on the flow code and could
  * be used elsewhere.
  */
 LLVMBasicBlockRef
-lp_build_insert_new_block(LLVMBuilderRef builder, const char *name)
+lp_build_insert_new_block(struct gallivm_state *gallivm, const char *name)
 {
    LLVMBasicBlockRef current_block;
    LLVMBasicBlockRef next_block;
    LLVMBasicBlockRef new_block;
 
    /* get current basic block */
-   current_block = LLVMGetInsertBlock(builder);
+   current_block = LLVMGetInsertBlock(gallivm->builder);
 
    /* check if there's another block after this one */
    next_block = LLVMGetNextBasicBlock(current_block);
    if (next_block) {
       /* insert the new block before the next block */
-      new_block = LLVMInsertBasicBlock(next_block, name);
+      new_block = LLVMInsertBasicBlockInContext(gallivm->context, next_block, name);
    }
    else {
       /* append new block after current block */
       LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
-      new_block = LLVMAppendBasicBlock(function, name);
+      new_block = LLVMAppendBasicBlockInContext(gallivm->context, function, name);
    }
 
    return new_block;
 }
 
 
-static LLVMBasicBlockRef
-lp_build_flow_insert_block(struct lp_build_flow_context *flow)
-{
-   return lp_build_insert_new_block(flow->builder, "");
-}
-
-
 /**
  * Begin a "skip" block.  Inside this block we can test a condition and
  * skip to the end of the block if the condition is false.
  */
 void
-lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
+lp_build_flow_skip_begin(struct lp_build_skip_context *skip,
+                         struct gallivm_state *gallivm)
 {
-   struct lp_build_flow_skip *skip;
-   LLVMBuilderRef builder;
-   unsigned i;
-
-   skip = &lp_build_flow_push(flow, LP_BUILD_FLOW_SKIP)->skip;
-   if(!skip)
-      return;
-
+   skip->gallivm = gallivm;
    /* create new basic block */
-   skip->block = lp_build_flow_insert_block(flow);
-
-   skip->num_variables = flow->num_variables;
-   if(!skip->num_variables) {
-      skip->phi = NULL;
-      return;
-   }
-
-   /* Allocate a Phi node for each variable in this skip scope */
-   skip->phi = MALLOC(skip->num_variables * sizeof *skip->phi);
-   if(!skip->phi) {
-      skip->num_variables = 0;
-      return;
-   }
-
-   builder = LLVMCreateBuilder();
-   LLVMPositionBuilderAtEnd(builder, skip->block);
-
-   /* create a Phi node for each variable */
-   for(i = 0; i < skip->num_variables; ++i)
-      skip->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), "");
-
-   LLVMDisposeBuilder(builder);
+   skip->block = lp_build_insert_new_block(gallivm, "skip");
 }
 
 
@@ -388,83 +96,59 @@ lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
  * skip block if the condition is true.
  */
 void
-lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
+lp_build_flow_skip_cond_break(struct lp_build_skip_context *skip,
                               LLVMValueRef cond)
 {
-   struct lp_build_flow_skip *skip;
-   LLVMBasicBlockRef current_block;
    LLVMBasicBlockRef new_block;
-   unsigned i;
-
-   skip = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SKIP)->skip;
-   if(!skip)
-      return;
-
-   current_block = LLVMGetInsertBlock(flow->builder);
-
-   new_block = lp_build_flow_insert_block(flow);
 
-   /* for each variable, update the Phi node with a (variable, block) pair */
-   for(i = 0; i < skip->num_variables; ++i) {
-      assert(*flow->variables[i]);
-      assert(LLVMTypeOf(skip->phi[i]) == LLVMTypeOf(*flow->variables[i]));
-      LLVMAddIncoming(skip->phi[i], flow->variables[i], &current_block, 1);
-   }
+   new_block = lp_build_insert_new_block(skip->gallivm, "");
 
    /* if cond is true, goto skip->block, else goto new_block */
-   LLVMBuildCondBr(flow->builder, cond, skip->block, new_block);
+   LLVMBuildCondBr(skip->gallivm->builder, cond, skip->block, new_block);
 
-   LLVMPositionBuilderAtEnd(flow->builder, new_block);
+   LLVMPositionBuilderAtEnd(skip->gallivm->builder, new_block);
 }
 
 
 void
-lp_build_flow_skip_end(struct lp_build_flow_context *flow)
+lp_build_flow_skip_end(struct lp_build_skip_context *skip)
 {
-   struct lp_build_flow_skip *skip;
-   LLVMBasicBlockRef current_block;
-   unsigned i;
-
-   skip = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SKIP)->skip;
-   if(!skip)
-      return;
-
-   current_block = LLVMGetInsertBlock(flow->builder);
-
-   /* add (variable, block) tuples to the phi nodes */
-   for(i = 0; i < skip->num_variables; ++i) {
-      assert(*flow->variables[i]);
-      assert(LLVMTypeOf(skip->phi[i]) == LLVMTypeOf(*flow->variables[i]));
-      LLVMAddIncoming(skip->phi[i], flow->variables[i], &current_block, 1);
-      *flow->variables[i] = skip->phi[i];
-   }
-
    /* goto block */
-   LLVMBuildBr(flow->builder, skip->block);
-   LLVMPositionBuilderAtEnd(flow->builder, skip->block);
-
-   FREE(skip->phi);
+   LLVMBuildBr(skip->gallivm->builder, skip->block);
+   LLVMPositionBuilderAtEnd(skip->gallivm->builder, skip->block);
 }
 
 
 /**
  * Check if the mask predicate is zero.  If so, jump to the end of the block.
  */
-static void
+void
 lp_build_mask_check(struct lp_build_mask_context *mask)
 {
-   LLVMBuilderRef builder = mask->flow->builder;
+   LLVMBuilderRef builder = mask->skip.gallivm->builder;
+   LLVMValueRef value;
    LLVMValueRef cond;
 
+   value = lp_build_mask_value(mask);
+
+   /*
+    * XXX this doesn't quite generate the most efficient code possible, if
+    * the masks are vectors which have all bits set to the same value
+    * in each element.
+    * movmskps/pmovmskb would be more efficient to get the required value
+    * into ordinary reg (certainly with 8 floats).
+    * Not sure if llvm could figure that out on its own.
+    */
+
    /* cond = (mask == 0) */
    cond = LLVMBuildICmp(builder,
                         LLVMIntEQ,
-                        LLVMBuildBitCast(builder, mask->value, mask->reg_type, ""),
+                        LLVMBuildBitCast(builder, value, mask->reg_type, ""),
                         LLVMConstNull(mask->reg_type),
                         "");
 
    /* if cond, goto end of block */
-   lp_build_flow_skip_cond_break(mask->flow, cond);
+   lp_build_flow_skip_cond_break(&mask->skip, cond);
 }
 
 
@@ -477,36 +161,43 @@ lp_build_mask_check(struct lp_build_mask_context *mask)
  */
 void
 lp_build_mask_begin(struct lp_build_mask_context *mask,
-                    struct lp_build_flow_context *flow,
+                    struct gallivm_state *gallivm,
                     struct lp_type type,
                     LLVMValueRef value)
 {
    memset(mask, 0, sizeof *mask);
 
-   mask->flow = flow;
-   mask->reg_type = LLVMIntType(type.width * type.length);
-   mask->value = value;
+   mask->reg_type = LLVMIntTypeInContext(gallivm->context, type.width * type.length);
+   mask->var = lp_build_alloca(gallivm,
+                               lp_build_int_vec_type(gallivm, type),
+                               "execution_mask");
 
-   lp_build_flow_scope_begin(flow);
-   lp_build_flow_scope_declare(flow, &mask->value);
-   lp_build_flow_skip_begin(flow);
+   LLVMBuildStore(gallivm->builder, value, mask->var);
 
-   lp_build_mask_check(mask);
+   lp_build_flow_skip_begin(&mask->skip, gallivm);
+}
+
+
+LLVMValueRef
+lp_build_mask_value(struct lp_build_mask_context *mask)
+{
+   return LLVMBuildLoad(mask->skip.gallivm->builder, mask->var, "");
 }
 
 
 /**
  * Update boolean mask with given value (bitwise AND).
  * Typically used to update the quad's pixel alive/killed mask
- * after depth testing, alpha testing, TGSI_OPCODE_KIL, etc.
+ * after depth testing, alpha testing, TGSI_OPCODE_KILL_IF, etc.
  */
 void
 lp_build_mask_update(struct lp_build_mask_context *mask,
                      LLVMValueRef value)
 {
-   mask->value = LLVMBuildAnd( mask->flow->builder, mask->value, value, "");
-
-   lp_build_mask_check(mask);
+   value = LLVMBuildAnd(mask->skip.gallivm->builder,
+                        lp_build_mask_value(mask),
+                        value, "");
+   LLVMBuildStore(mask->skip.gallivm->builder, value, mask->var);
 }
 
 
@@ -516,42 +207,42 @@ lp_build_mask_update(struct lp_build_mask_context *mask,
 LLVMValueRef
 lp_build_mask_end(struct lp_build_mask_context *mask)
 {
-   lp_build_flow_skip_end(mask->flow);
-   lp_build_flow_scope_end(mask->flow);
-   return mask->value;
+   lp_build_flow_skip_end(&mask->skip);
+   return lp_build_mask_value(mask);
 }
 
 
 
 void
-lp_build_loop_begin(LLVMBuilderRef builder,
-                    LLVMValueRef start,
-                    struct lp_build_loop_state *state)
+lp_build_loop_begin(struct lp_build_loop_state *state,
+                    struct gallivm_state *gallivm,
+                    LLVMValueRef start)
+                    
 {
-   LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
-   LLVMValueRef function = LLVMGetBasicBlockParent(block);
+   LLVMBuilderRef builder = gallivm->builder;
 
-   state->block = LLVMAppendBasicBlock(function, "loop");
+   state->block = lp_build_insert_new_block(gallivm, "loop_begin");
 
-   LLVMBuildBr(builder, state->block);
+   state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter");
+   state->gallivm = gallivm;
 
-   LLVMPositionBuilderAtEnd(builder, state->block);
+   LLVMBuildStore(builder, start, state->counter_var);
 
-   state->counter = LLVMBuildPhi(builder, LLVMTypeOf(start), "");
+   LLVMBuildBr(builder, state->block);
 
-   LLVMAddIncoming(state->counter, &start, &block, 1);
+   LLVMPositionBuilderAtEnd(builder, state->block);
 
+   state->counter = LLVMBuildLoad(builder, state->counter_var, "");
 }
 
 
 void
-lp_build_loop_end(LLVMBuilderRef builder,
-                  LLVMValueRef end,
-                  LLVMValueRef step,
-                  struct lp_build_loop_state *state)
+lp_build_loop_end_cond(struct lp_build_loop_state *state,
+                       LLVMValueRef end,
+                       LLVMValueRef step,
+                       LLVMIntPredicate llvm_cond)
 {
-   LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
-   LLVMValueRef function = LLVMGetBasicBlockParent(block);
+   LLVMBuilderRef builder = state->gallivm->builder;
    LLVMValueRef next;
    LLVMValueRef cond;
    LLVMBasicBlockRef after_block;
@@ -561,46 +252,109 @@ lp_build_loop_end(LLVMBuilderRef builder,
 
    next = LLVMBuildAdd(builder, state->counter, step, "");
 
-   cond = LLVMBuildICmp(builder, LLVMIntNE, next, end, "");
+   LLVMBuildStore(builder, next, state->counter_var);
 
-   after_block = LLVMAppendBasicBlock(function, "");
+   cond = LLVMBuildICmp(builder, llvm_cond, next, end, "");
 
-   LLVMBuildCondBr(builder, cond, after_block, state->block);
+   after_block = lp_build_insert_new_block(state->gallivm, "loop_end");
 
-   LLVMAddIncoming(state->counter, &next, &block, 1);
+   LLVMBuildCondBr(builder, cond, after_block, state->block);
 
    LLVMPositionBuilderAtEnd(builder, after_block);
+
+   state->counter = LLVMBuildLoad(builder, state->counter_var, "");
 }
 
 void
-lp_build_loop_end_cond(LLVMBuilderRef builder,
-                       LLVMValueRef end,
-                       LLVMValueRef step,
-                       int llvm_cond,
-                       struct lp_build_loop_state *state)
+lp_build_loop_force_set_counter(struct lp_build_loop_state *state,
+                          LLVMValueRef end)
 {
-   LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
-   LLVMValueRef function = LLVMGetBasicBlockParent(block);
-   LLVMValueRef next;
-   LLVMValueRef cond;
-   LLVMBasicBlockRef after_block;
+   LLVMBuilderRef builder = state->gallivm->builder;
+   LLVMBuildStore(builder, end, state->counter_var);
+}
 
-   if (!step)
-      step = LLVMConstInt(LLVMTypeOf(end), 1, 0);
+void
+lp_build_loop_force_reload_counter(struct lp_build_loop_state *state)
+{
+   LLVMBuilderRef builder = state->gallivm->builder;
+   state->counter = LLVMBuildLoad(builder, state->counter_var, "");
+}
 
-   next = LLVMBuildAdd(builder, state->counter, step, "");
+void
+lp_build_loop_end(struct lp_build_loop_state *state,
+                  LLVMValueRef end,
+                  LLVMValueRef step)
+{
+   lp_build_loop_end_cond(state, end, step, LLVMIntNE);
+}
 
-   cond = LLVMBuildICmp(builder, llvm_cond, next, end, "");
+/**
+ * Creates a c-style for loop,
+ * contrasts lp_build_loop as this checks condition on entry
+ * e.g. for(i = start; i cmp_op end; i += step)
+ * \param state      the for loop state, initialized here
+ * \param gallivm    the gallivm state
+ * \param start      starting value of iterator
+ * \param cmp_op     comparison operator used for comparing current value with end value
+ * \param end        value used to compare against iterator
+ * \param step       value added to iterator at end of each loop
+ */
+void
+lp_build_for_loop_begin(struct lp_build_for_loop_state *state,
+                        struct gallivm_state *gallivm,
+                        LLVMValueRef start,
+                        LLVMIntPredicate cmp_op,
+                        LLVMValueRef end,
+                        LLVMValueRef step)
+{
+   LLVMBuilderRef builder = gallivm->builder;
 
-   after_block = LLVMAppendBasicBlock(function, "");
+   assert(LLVMTypeOf(start) == LLVMTypeOf(end));
+   assert(LLVMTypeOf(start) == LLVMTypeOf(step));
 
-   LLVMBuildCondBr(builder, cond, after_block, state->block);
+   state->begin = lp_build_insert_new_block(gallivm, "loop_begin");
+   state->step  = step;
+   state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter");
+   state->gallivm = gallivm;
+   state->cond = cmp_op;
+   state->end = end;
 
-   LLVMAddIncoming(state->counter, &next, &block, 1);
+   LLVMBuildStore(builder, start, state->counter_var);
+   LLVMBuildBr(builder, state->begin);
 
-   LLVMPositionBuilderAtEnd(builder, after_block);
+   LLVMPositionBuilderAtEnd(builder, state->begin);
+   state->counter = LLVMBuildLoad(builder, state->counter_var, "");
+
+   state->body = lp_build_insert_new_block(gallivm, "loop_body");
+   LLVMPositionBuilderAtEnd(builder, state->body);
 }
 
+/**
+ * End the for loop.
+ */
+void
+lp_build_for_loop_end(struct lp_build_for_loop_state *state)
+{
+   LLVMValueRef next, cond;
+   LLVMBuilderRef builder = state->gallivm->builder;
+
+   next = LLVMBuildAdd(builder, state->counter, state->step, "");
+   LLVMBuildStore(builder, next, state->counter_var);
+   LLVMBuildBr(builder, state->begin);
+
+   state->exit = lp_build_insert_new_block(state->gallivm, "loop_exit");
+
+   /*
+    * We build the comparison for the begin block here,
+    * if we build it earlier the output llvm ir is not human readable
+    * as the code produced is not in the standard begin -> body -> end order.
+    */
+   LLVMPositionBuilderAtEnd(builder, state->begin);
+   cond = LLVMBuildICmp(builder, state->cond, state->counter, state->end, "");
+   LLVMBuildCondBr(builder, cond, state->body, state->exit);
+
+   LLVMPositionBuilderAtEnd(builder, state->exit);
+}
 
 
 /*
@@ -616,24 +370,16 @@ lp_build_loop_end_cond(LLVMBuilderRef builder,
 
   Is built with:
 
-     LLVMValueRef x = LLVMGetUndef();  // or something else
+     // x needs an alloca variable
+     x = lp_build_alloca(builder, type, "x");
 
-     flow = lp_build_flow_create(builder);
 
-        lp_build_flow_scope_begin(flow);
+     lp_build_if(ctx, builder, cond);
+        LLVMBuildStore(LLVMBuildAdd(1, 2), x);
+     lp_build_else(ctx);
+        LLVMBuildStore(LLVMBuildAdd(2, 3). x);
+     lp_build_endif(ctx);
 
-           // x needs a phi node
-           lp_build_flow_scope_declare(flow, &x);
-
-           lp_build_if(ctx, flow, builder, cond);
-              x = LLVMAdd(1, 2);
-           lp_build_else(ctx);
-              x = LLVMAdd(2, 3);
-           lp_build_endif(ctx);
-
-        lp_build_flow_scope_end(flow);
-
-     lp_build_flow_destroy(flow);
  */
 
 
@@ -642,53 +388,28 @@ lp_build_loop_end_cond(LLVMBuilderRef builder,
  * Begin an if/else/endif construct.
  */
 void
-lp_build_if(struct lp_build_if_state *ctx,
-            struct lp_build_flow_context *flow,
-            LLVMBuilderRef builder,
+lp_build_if(struct lp_build_if_state *ifthen,
+            struct gallivm_state *gallivm,
             LLVMValueRef condition)
 {
-   LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
-   struct lp_build_flow_if *ifthen;
-   unsigned i;
-
-   memset(ctx, 0, sizeof(*ctx));
-   ctx->builder = builder;
-   ctx->flow = flow;
+   LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder);
 
-   /* push/create new scope */
-   ifthen = &lp_build_flow_push(flow, LP_BUILD_FLOW_IF)->ifthen;
-   assert(ifthen);
-
-   ifthen->num_variables = flow->num_variables;
+   memset(ifthen, 0, sizeof *ifthen);
+   ifthen->gallivm = gallivm;
    ifthen->condition = condition;
    ifthen->entry_block = block;
 
-   /* create a Phi node for each variable in this flow scope */
-   ifthen->phi = MALLOC(ifthen->num_variables * sizeof(*ifthen->phi));
-   if (!ifthen->phi) {
-      ifthen->num_variables = 0;
-      return;
-   }
-
    /* create endif/merge basic block for the phi functions */
-   ifthen->merge_block = lp_build_insert_new_block(builder, "endif-block");
-   LLVMPositionBuilderAtEnd(builder, ifthen->merge_block);
-
-   /* create a phi node for each variable */
-   for (i = 0; i < flow->num_variables; i++) {
-      ifthen->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), "");
-
-      /* add add the initial value of the var from the entry block */
-      if (!LLVMIsUndef(*flow->variables[i]))
-         LLVMAddIncoming(ifthen->phi[i], flow->variables[i],
-                         &ifthen->entry_block, 1);
-   }
+   ifthen->merge_block = lp_build_insert_new_block(gallivm, "endif-block");
 
    /* create/insert true_block before merge_block */
-   ifthen->true_block = LLVMInsertBasicBlock(ifthen->merge_block, "if-true-block");
+   ifthen->true_block =
+      LLVMInsertBasicBlockInContext(gallivm->context,
+                                    ifthen->merge_block,
+                                    "if-true-block");
 
    /* successive code goes into the true block */
-   LLVMPositionBuilderAtEnd(builder, ifthen->true_block);
+   LLVMPositionBuilderAtEnd(gallivm->builder, ifthen->true_block);
 }
 
 
@@ -696,27 +417,21 @@ lp_build_if(struct lp_build_if_state *ctx,
  * Begin else-part of a conditional
  */
 void
-lp_build_else(struct lp_build_if_state *ctx)
+lp_build_else(struct lp_build_if_state *ifthen)
 {
-   struct lp_build_flow_context *flow = ctx->flow;
-   struct lp_build_flow_if *ifthen;
-   unsigned i;
-
-   ifthen = &lp_build_flow_peek(flow, LP_BUILD_FLOW_IF)->ifthen;
-   assert(ifthen);
-
-   /* for each variable, update the Phi node with a (variable, block) pair */
-   LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
-   for (i = 0; i < flow->num_variables; i++) {
-      assert(*flow->variables[i]);
-      LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->true_block, 1);
-   }
+   LLVMBuilderRef builder = ifthen->gallivm->builder;
+
+   /* Append an unconditional Br(anch) instruction on the true_block */
+   LLVMBuildBr(builder, ifthen->merge_block);
 
    /* create/insert false_block before the merge block */
-   ifthen->false_block = LLVMInsertBasicBlock(ifthen->merge_block, "if-false-block");
+   ifthen->false_block =
+      LLVMInsertBasicBlockInContext(ifthen->gallivm->context,
+                                    ifthen->merge_block,
+                                    "if-false-block");
 
    /* successive code goes into the else block */
-   LLVMPositionBuilderAtEnd(ctx->builder, ifthen->false_block);
+   LLVMPositionBuilderAtEnd(builder, ifthen->false_block);
 }
 
 
@@ -724,75 +439,52 @@ lp_build_else(struct lp_build_if_state *ctx)
  * End a conditional.
  */
 void
-lp_build_endif(struct lp_build_if_state *ctx)
+lp_build_endif(struct lp_build_if_state *ifthen)
 {
-   struct lp_build_flow_context *flow = ctx->flow;
-   struct lp_build_flow_if *ifthen;
-   LLVMBasicBlockRef curBlock = LLVMGetInsertBlock(ctx->builder);
-   unsigned i;
-
-   ifthen = &lp_build_flow_pop(flow, LP_BUILD_FLOW_IF)->ifthen;
-   assert(ifthen);
+   LLVMBuilderRef builder = ifthen->gallivm->builder;
 
    /* Insert branch to the merge block from current block */
-   LLVMBuildBr(ctx->builder, ifthen->merge_block);
+   LLVMBuildBr(builder, ifthen->merge_block);
 
-   if (ifthen->false_block) {
-      LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
-      /* for each variable, update the Phi node with a (variable, block) pair */
-      for (i = 0; i < flow->num_variables; i++) {
-         assert(*flow->variables[i]);
-         LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &curBlock, 1);
-         /* replace the variable ref with the phi function */
-         *flow->variables[i] = ifthen->phi[i];
-      }
-   }
-   else {
-      /* no else clause */
-      LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
-      for (i = 0; i < flow->num_variables; i++) {
-         assert(*flow->variables[i]);
-         LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->true_block, 1);
-
-         /* replace the variable ref with the phi function */
-         *flow->variables[i] = ifthen->phi[i];
-      }
-   }
-
-   FREE(ifthen->phi);
-
-   /***
-    *** Now patch in the various branch instructions.
-    ***/
+   /*
+    * Now patch in the various branch instructions.
+    */
 
    /* Insert the conditional branch instruction at the end of entry_block */
-   LLVMPositionBuilderAtEnd(ctx->builder, ifthen->entry_block);
+   LLVMPositionBuilderAtEnd(builder, ifthen->entry_block);
    if (ifthen->false_block) {
       /* we have an else clause */
-      LLVMBuildCondBr(ctx->builder, ifthen->condition,
+      LLVMBuildCondBr(builder, ifthen->condition,
                       ifthen->true_block, ifthen->false_block);
    }
    else {
       /* no else clause */
-      LLVMBuildCondBr(ctx->builder, ifthen->condition,
+      LLVMBuildCondBr(builder, ifthen->condition,
                       ifthen->true_block, ifthen->merge_block);
    }
 
-   /* Insert branch from end of true_block to merge_block */
-   if (ifthen->false_block) {
-      /* Append an unconditional Br(anch) instruction on the true_block */
-      LLVMPositionBuilderAtEnd(ctx->builder, ifthen->true_block);
-      LLVMBuildBr(ctx->builder, ifthen->merge_block);
-   }
-   else {
-      /* No else clause.
-       * Note that we've already inserted the branch at the end of
-       * true_block.  See the very first LLVMBuildBr() call in this function.
-       */
+   /* Resume building code at end of the ifthen->merge_block */
+   LLVMPositionBuilderAtEnd(builder, ifthen->merge_block);
+}
+
+
+static LLVMBuilderRef
+create_builder_at_entry(struct gallivm_state *gallivm)
+{
+   LLVMBuilderRef builder = gallivm->builder;
+   LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
+   LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
+   LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
+   LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
+   LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
+
+   if (first_instr) {
+      LLVMPositionBuilderBefore(first_builder, first_instr);
+   } else {
+      LLVMPositionBuilderAtEnd(first_builder, first_block);
    }
 
-   /* Resume building code at end of the ifthen->merge_block */
-   LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
+   return first_builder;
 }
 
 
@@ -812,22 +504,33 @@ lp_build_endif(struct lp_build_if_state *ctx)
  * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
  */
 LLVMValueRef
-lp_build_alloca(LLVMBuilderRef builder,
+lp_build_alloca(struct gallivm_state *gallivm,
                 LLVMTypeRef type,
                 const char *name)
 {
-   LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
-   LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
-   LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
-   LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
-   LLVMBuilderRef first_builder = LLVMCreateBuilder();
+   LLVMBuilderRef builder = gallivm->builder;
+   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
    LLVMValueRef res;
 
-   if (first_instr) {
-      LLVMPositionBuilderBefore(first_builder, first_instr);
-   } else {
-      LLVMPositionBuilderAtEnd(first_builder, first_block);
-   }
+   res = LLVMBuildAlloca(first_builder, type, name);
+   LLVMBuildStore(builder, LLVMConstNull(type), res);
+
+   LLVMDisposeBuilder(first_builder);
+
+   return res;
+}
+
+
+/**
+ * Like lp_build_alloca, but do not zero-initialize the variable.
+ */
+LLVMValueRef
+lp_build_alloca_undef(struct gallivm_state *gallivm,
+                      LLVMTypeRef type,
+                      const char *name)
+{
+   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
+   LLVMValueRef res;
 
    res = LLVMBuildAlloca(first_builder, type, name);
 
@@ -852,24 +555,14 @@ lp_build_alloca(LLVMBuilderRef builder,
  * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
  */
 LLVMValueRef
-lp_build_array_alloca(LLVMBuilderRef builder,
+lp_build_array_alloca(struct gallivm_state *gallivm,
                       LLVMTypeRef type,
                       LLVMValueRef count,
                       const char *name)
 {
-   LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
-   LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
-   LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
-   LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
-   LLVMBuilderRef first_builder = LLVMCreateBuilder();
+   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
    LLVMValueRef res;
 
-   if (first_instr) {
-      LLVMPositionBuilderBefore(first_builder, first_instr);
-   } else {
-      LLVMPositionBuilderAtEnd(first_builder, first_block);
-   }
-
    res = LLVMBuildArrayAlloca(first_builder, type, count, name);
 
    LLVMDisposeBuilder(first_builder);