summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/gallivm
diff options
context:
space:
mode:
authorRoland Scheidegger <sroland@vmware.com>2010-04-30 15:27:13 +0200
committerRoland Scheidegger <sroland@vmware.com>2010-04-30 15:27:13 +0200
commit7662e3519bef3802024da3050b886068281e02b1 (patch)
treebc5bf675e67febffaf9e4d1fadd139e8c253ae32 /src/gallium/auxiliary/gallivm
parent9a966b93c03aecac8eb72e6133aa9a2f2c7673f3 (diff)
parent7c769bef052fc1936d7ab33e291bb4646dc5b0d1 (diff)
Merge commit 'origin/master' into gallium-msaa
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c18
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_flow.c75
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_flow.h10
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_aos.c7
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_logic.c12
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_logic.h3
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c5
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c47
8 files changed, 120 insertions, 57 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 5f9d4c62d1..20ae958714 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -1210,6 +1210,14 @@ LLVMValueRef
lp_build_cos(struct lp_build_context *bld,
LLVMValueRef a)
{
+#ifdef PIPE_OS_WINDOWS
+ /*
+ * FIXME: X86 backend translates llvm.cos.v4f32 to 4 calls to CRT's cosf()
+ * which is neither efficient nor does the CRT linkage work on Windows
+ * causing segmentation fault. So simply disable the code for now.
+ */
+ return bld->one;
+#else
const struct lp_type type = bld->type;
LLVMTypeRef vec_type = lp_build_vec_type(type);
char intrinsic[32];
@@ -1220,6 +1228,7 @@ lp_build_cos(struct lp_build_context *bld,
util_snprintf(intrinsic, sizeof intrinsic, "llvm.cos.v%uf%u", type.length, type.width);
return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a);
+#endif
}
@@ -1230,6 +1239,14 @@ LLVMValueRef
lp_build_sin(struct lp_build_context *bld,
LLVMValueRef a)
{
+#ifdef PIPE_OS_WINDOWS
+ /*
+ * FIXME: X86 backend translates llvm.sin.v4f32 to 4 calls to CRT's sinf()
+ * which is neither efficient nor does the CRT linkage work on Windows
+ * causing segmentation fault. So simply disable the code for now.
+ */
+ return bld->zero;
+#else
const struct lp_type type = bld->type;
LLVMTypeRef vec_type = lp_build_vec_type(type);
char intrinsic[32];
@@ -1240,6 +1257,7 @@ lp_build_sin(struct lp_build_context *bld,
util_snprintf(intrinsic, sizeof intrinsic, "llvm.sin.v%uf%u", type.length, type.width);
return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a);
+#endif
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.c b/src/gallium/auxiliary/gallivm/lp_bld_flow.c
index e60ab4f6ba..8f15b1d287 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 745838570c..fffb493a93 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 a5a019fa92..6257e9a404 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 a3b6970116..d13fa1a5d0 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 00a8c75019..29f9fc3b20 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_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 54ef921678..74dc9e1d81 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -1830,6 +1830,11 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
LLVMValueRef unswizzled[4];
LLVMValueRef stride;
+ assert(bld->static_state->target == PIPE_TEXTURE_2D);
+ assert(bld->static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR);
+ assert(bld->static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR);
+ assert(bld->static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE);
+
lp_build_context_init(&i32, builder, lp_type_int_vec(32));
lp_build_context_init(&h16, builder, lp_type_ufixed(16));
lp_build_context_init(&u8n, builder, lp_type_unorm(8));
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index fac90c6006..d3c769e28b 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;
}
@@ -1600,18 +1589,10 @@ emit_instruction(
lp_exec_mask_cond_push(&bld->exec_mask, tmp0);
break;
- case TGSI_OPCODE_BGNFOR:
- /* fall through */
case TGSI_OPCODE_BGNLOOP:
lp_exec_bgnloop(&bld->exec_mask);
break;
- case TGSI_OPCODE_REP:
- /* deprecated */
- assert(0);
- return FALSE;
- break;
-
case TGSI_OPCODE_ELSE:
lp_exec_mask_cond_invert(&bld->exec_mask);
break;
@@ -1620,18 +1601,10 @@ emit_instruction(
lp_exec_mask_cond_pop(&bld->exec_mask);
break;
- case TGSI_OPCODE_ENDFOR:
- /* fall-through */
case TGSI_OPCODE_ENDLOOP:
lp_exec_endloop(&bld->exec_mask);
break;
- case TGSI_OPCODE_ENDREP:
- /* deprecated */
- assert(0);
- return FALSE;
- break;
-
case TGSI_OPCODE_PUSHA:
/* deprecated? */
assert(0);