gallivm: Ensure all allocas are in the first block.
Refactor the code to make this easier.
This commit is contained in:
parent
96df6064b5
commit
a18c210a95
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue