gallivm: Ensure all allocas are in the first block.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 27 Apr 2010 12:20:12 +0000 (13:20 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 27 Apr 2010 12:20:51 +0000 (13:20 +0100)
Refactor the code to make this easier.

src/gallium/auxiliary/gallivm/lp_bld_flow.c
src/gallium/auxiliary/gallivm/lp_bld_flow.h
src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
src/gallium/auxiliary/gallivm/lp_bld_logic.c
src/gallium/auxiliary/gallivm/lp_bld_logic.h
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c

index e60ab4f6ba193f7c94b9fa12a0ee383618ccb913..8f15b1d287d40076d75de1bf37405a78cebd33ab 100644 (file)
@@ -792,3 +792,78 @@ lp_build_endif(struct lp_build_if_state *ctx)
    /* Resume building code at end of the ifthen->merge_block */
    LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
 }
+
+
+/**
+ * Allocate a scalar (or vector) variable.
+ *
+ * Although not strictly part of control flow, control flow has deep impact in
+ * how variables should be allocated.
+ *
+ * The mem2reg optimization pass is the recommended way to dealing with mutable
+ * variables, and SSA. It looks for allocas and if it can handle them, it
+ * promotes them, but only looks for alloca instructions in the entry block of
+ * the function. Being in the entry block guarantees that the alloca is only
+ * executed once, which makes analysis simpler.
+ *
+ * See also:
+ * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
+ */
+LLVMValueRef
+lp_build_alloca(LLVMBuilderRef builder,
+                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();
+   LLVMValueRef res;
+
+   LLVMPositionBuilderAtEnd(first_builder, first_block);
+   LLVMPositionBuilderBefore(first_builder, first_instr);
+
+   res = LLVMBuildAlloca(first_builder, type, name);
+
+   LLVMDisposeBuilder(first_builder);
+
+   return res;
+}
+
+
+/**
+ * Allocate an array of scalars/vectors.
+ *
+ * mem2reg pass is not capable of promoting structs or arrays to registers, but
+ * we still put it in the first block anyway as failure to put allocas in the
+ * first block may prevent the X86 backend from successfully align the stack as
+ * required.
+ *
+ * Also the scalarrepl pass is supossedly more powerful and can promote
+ * arrays in many cases.
+ *
+ * See also:
+ * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
+ */
+LLVMValueRef
+lp_build_array_alloca(LLVMBuilderRef builder,
+                      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();
+   LLVMValueRef res;
+
+   LLVMPositionBuilderBefore(first_builder, first_instr);
+
+   res = LLVMBuildArrayAlloca(first_builder, type, count, name);
+
+   LLVMDisposeBuilder(first_builder);
+
+   return res;
+}
index 745838570c87629a8767ecf70d8b4417ffa6d8cc..fffb493a93b2470a9a542e14aea7946bae54026c 100644 (file)
@@ -156,5 +156,15 @@ lp_build_endif(struct lp_build_if_state *ctx);
 LLVMBasicBlockRef
 lp_build_insert_new_block(LLVMBuilderRef builder, const char *name);
 
+LLVMValueRef
+lp_build_alloca(LLVMBuilderRef builder,
+                LLVMTypeRef type,
+                const char *name);
+
+LLVMValueRef
+lp_build_array_alloca(LLVMBuilderRef builder,
+                      LLVMTypeRef type,
+                      LLVMValueRef count,
+                      const char *name);
 
 #endif /* !LP_BLD_FLOW_H */
index a5a019fa92a005968385f705daff4cdd088a2b22..6257e9a4047cf5de7bc3026e4253c43e71585054 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "lp_bld_init.h"
 #include "lp_bld_type.h"
+#include "lp_bld_flow.h"
 #include "lp_bld_format.h"
 
 
@@ -370,11 +371,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
          LLVMAddGlobalMapping(lp_build_engine, function, format_desc->fetch_rgba_float);
       }
 
-      /*
-       * XXX: this should better go to the first block in the function
-       */
-
-      tmp = LLVMBuildAlloca(builder, LLVMVectorType(LLVMFloatType(), 4), "");
+      tmp = lp_build_alloca(builder, LLVMVectorType(LLVMFloatType(), 4), "");
 
       /*
        * Invoke format_desc->fetch_rgba_float() for each pixel and insert the result
index a3b697011626daba23662bd98a41f695d6ce3c17..d13fa1a5d043b4f5cf9c9f8e23a477647fe534bd 100644 (file)
@@ -472,18 +472,6 @@ lp_build_select_aos(struct lp_build_context *bld,
    }
 }
 
-LLVMValueRef
-lp_build_alloca(struct lp_build_context *bld)
-{
-   const struct lp_type type = bld->type;
-
-   if (type.length > 1) { /*vector*/
-      return LLVMBuildAlloca(bld->builder, lp_build_vec_type(type), "");
-   } else { /*scalar*/
-      return LLVMBuildAlloca(bld->builder, lp_build_elem_type(type), "");
-   }
-}
-
 
 /** Return (a & ~b) */
 LLVMValueRef
index 00a8c750196d0a62c246fb16ab32acbba3a49f67..29f9fc3b205af3e415eb462403c115a960335499 100644 (file)
@@ -76,9 +76,6 @@ lp_build_select_aos(struct lp_build_context *bld,
                     LLVMValueRef b,
                     const boolean cond[4]);
 
-LLVMValueRef
-lp_build_alloca(struct lp_build_context *bld);
-
 
 LLVMValueRef
 lp_build_andc(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b);
index fac90c60064cccedb482e0bf34d6df7511ba5058..b9b13d8d6b39a897f30a0890a771cceeb9a11bc7 100644 (file)
@@ -744,22 +744,11 @@ emit_declaration(
    struct lp_build_tgsi_soa_context *bld,
    const struct tgsi_full_declaration *decl)
 {
+   LLVMTypeRef vec_type = lp_build_vec_type(bld->base.type);
+
    unsigned first = decl->Range.First;
    unsigned last = decl->Range.Last;
    unsigned idx, i;
-   LLVMBasicBlockRef current_block =
-      LLVMGetInsertBlock(bld->base.builder);
-   LLVMBasicBlockRef first_block =
-      LLVMGetEntryBasicBlock(
-         LLVMGetBasicBlockParent(current_block));
-   LLVMValueRef first_inst =
-      LLVMGetFirstInstruction(first_block);
-
-   /* we want alloca's to be the first instruction
-    * in the function so we need to rewind the builder
-    * to the very beginning */
-   LLVMPositionBuilderBefore(bld->base.builder,
-                             first_inst);
 
    for (idx = first; idx <= last; ++idx) {
       switch (decl->Declaration.File) {
@@ -767,23 +756,25 @@ emit_declaration(
          if (bld->has_indirect_addressing) {
             LLVMValueRef val = LLVMConstInt(LLVMInt32Type(),
                                             last*4 + 4, 0);
-            bld->temps_array = LLVMBuildArrayAlloca(bld->base.builder,
-                                                    lp_build_vec_type(bld->base.type),
-                                                    val, "");
+            bld->temps_array = lp_build_array_alloca(bld->base.builder,
+                                                     vec_type, val, "");
          } else {
             for (i = 0; i < NUM_CHANNELS; i++)
-               bld->temps[idx][i] = lp_build_alloca(&bld->base);
+               bld->temps[idx][i] = lp_build_alloca(bld->base.builder,
+                                                    vec_type, "");
          }
          break;
 
       case TGSI_FILE_OUTPUT:
          for (i = 0; i < NUM_CHANNELS; i++)
-            bld->outputs[idx][i] = lp_build_alloca(&bld->base);
+            bld->outputs[idx][i] = lp_build_alloca(bld->base.builder,
+                                                   vec_type, "");
          break;
 
       case TGSI_FILE_ADDRESS:
          for (i = 0; i < NUM_CHANNELS; i++)
-            bld->addr[idx][i] = lp_build_alloca(&bld->base);
+            bld->addr[idx][i] = lp_build_alloca(bld->base.builder,
+                                                vec_type, "");
          break;
 
       default:
@@ -792,8 +783,6 @@ emit_declaration(
       }
    }
 
-   LLVMPositionBuilderAtEnd(bld->base.builder,
-                            current_block);
    return TRUE;
 }