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 */
|
/* Resume building code at end of the ifthen->merge_block */
|
||||||
LLVMPositionBuilderAtEnd(ctx->builder, 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
|
LLVMBasicBlockRef
|
||||||
lp_build_insert_new_block(LLVMBuilderRef builder, const char *name);
|
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 */
|
#endif /* !LP_BLD_FLOW_H */
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#include "lp_bld_init.h"
|
#include "lp_bld_init.h"
|
||||||
#include "lp_bld_type.h"
|
#include "lp_bld_type.h"
|
||||||
|
#include "lp_bld_flow.h"
|
||||||
#include "lp_bld_format.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);
|
LLVMAddGlobalMapping(lp_build_engine, function, format_desc->fetch_rgba_float);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
tmp = lp_build_alloca(builder, LLVMVectorType(LLVMFloatType(), 4), "");
|
||||||
* XXX: this should better go to the first block in the function
|
|
||||||
*/
|
|
||||||
|
|
||||||
tmp = LLVMBuildAlloca(builder, LLVMVectorType(LLVMFloatType(), 4), "");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke format_desc->fetch_rgba_float() for each pixel and insert the result
|
* 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) */
|
/** Return (a & ~b) */
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
|
|
|
@ -76,9 +76,6 @@ lp_build_select_aos(struct lp_build_context *bld,
|
||||||
LLVMValueRef b,
|
LLVMValueRef b,
|
||||||
const boolean cond[4]);
|
const boolean cond[4]);
|
||||||
|
|
||||||
LLVMValueRef
|
|
||||||
lp_build_alloca(struct lp_build_context *bld);
|
|
||||||
|
|
||||||
|
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
lp_build_andc(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b);
|
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,
|
struct lp_build_tgsi_soa_context *bld,
|
||||||
const struct tgsi_full_declaration *decl)
|
const struct tgsi_full_declaration *decl)
|
||||||
{
|
{
|
||||||
|
LLVMTypeRef vec_type = lp_build_vec_type(bld->base.type);
|
||||||
|
|
||||||
unsigned first = decl->Range.First;
|
unsigned first = decl->Range.First;
|
||||||
unsigned last = decl->Range.Last;
|
unsigned last = decl->Range.Last;
|
||||||
unsigned idx, i;
|
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) {
|
for (idx = first; idx <= last; ++idx) {
|
||||||
switch (decl->Declaration.File) {
|
switch (decl->Declaration.File) {
|
||||||
|
@ -767,23 +756,25 @@ emit_declaration(
|
||||||
if (bld->has_indirect_addressing) {
|
if (bld->has_indirect_addressing) {
|
||||||
LLVMValueRef val = LLVMConstInt(LLVMInt32Type(),
|
LLVMValueRef val = LLVMConstInt(LLVMInt32Type(),
|
||||||
last*4 + 4, 0);
|
last*4 + 4, 0);
|
||||||
bld->temps_array = LLVMBuildArrayAlloca(bld->base.builder,
|
bld->temps_array = lp_build_array_alloca(bld->base.builder,
|
||||||
lp_build_vec_type(bld->base.type),
|
vec_type, val, "");
|
||||||
val, "");
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < NUM_CHANNELS; i++)
|
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;
|
break;
|
||||||
|
|
||||||
case TGSI_FILE_OUTPUT:
|
case TGSI_FILE_OUTPUT:
|
||||||
for (i = 0; i < NUM_CHANNELS; i++)
|
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;
|
break;
|
||||||
|
|
||||||
case TGSI_FILE_ADDRESS:
|
case TGSI_FILE_ADDRESS:
|
||||||
for (i = 0; i < NUM_CHANNELS; i++)
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -792,8 +783,6 @@ emit_declaration(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(bld->base.builder,
|
|
||||||
current_block);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue