Mesa (master): gallivm: Ensure all allocas are in the first block.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Tue Apr 27 12:21:14 UTC 2010


Module: Mesa
Branch: master
Commit: a18c210a95794c79c6f26dbf4c66d4a85e29169d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a18c210a95794c79c6f26dbf4c66d4a85e29169d

Author: José Fonseca <jfonseca at vmware.com>
Date:   Tue Apr 27 13:20:12 2010 +0100

gallivm: Ensure all allocas are in the first block.

Refactor the code to make this easier.

---

 src/gallium/auxiliary/gallivm/lp_bld_flow.c       |   75 +++++++++++++++++++++
 src/gallium/auxiliary/gallivm/lp_bld_flow.h       |   10 +++
 src/gallium/auxiliary/gallivm/lp_bld_format_aos.c |    7 +--
 src/gallium/auxiliary/gallivm/lp_bld_logic.c      |   12 ---
 src/gallium/auxiliary/gallivm/lp_bld_logic.h      |    3 -
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |   31 +++------
 6 files changed, 97 insertions(+), 41 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.c b/src/gallium/auxiliary/gallivm/lp_bld_flow.c
index e60ab4f..8f15b1d 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_flow.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.c
@@ -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;
+}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.h b/src/gallium/auxiliary/gallivm/lp_bld_flow.h
index 7458385..fffb493 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_flow.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.h
@@ -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 */
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index a5a019f..6257e9a 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
@@ -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
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.c b/src/gallium/auxiliary/gallivm/lp_bld_logic.c
index a3b6970..d13fa1a 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_logic.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.c
@@ -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
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.h b/src/gallium/auxiliary/gallivm/lp_bld_logic.h
index 00a8c75..29f9fc3 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_logic.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.h
@@ -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);
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index fac90c6..b9b13d8 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -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;
 }
 




More information about the mesa-commit mailing list