Refactor the code to make this easier.
/* 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;
+}
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 */
#include "lp_bld_init.h"
#include "lp_bld_type.h"
+#include "lp_bld_flow.h"
#include "lp_bld_format.h"
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
}
}
-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
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);
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) {
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:
}
}
- LLVMPositionBuilderAtEnd(bld->base.builder,
- current_block);
return TRUE;
}