value = lp_build_mask_value(mask);
+ /*
+ * XXX this doesn't quite generate the most efficient code possible, if
+ * the masks are vectors which have all bits set to the same value
+ * in each element.
+ * movmskps/pmovmskb would be more efficient to get the required value
+ * into ordinary reg (certainly with 8 floats).
+ * Not sure if llvm could figure that out on its own.
+ */
+
/* cond = (mask == 0) */
cond = LLVMBuildICmp(builder,
LLVMIntEQ,
/**
* Update boolean mask with given value (bitwise AND).
* Typically used to update the quad's pixel alive/killed mask
- * after depth testing, alpha testing, TGSI_OPCODE_KIL, etc.
+ * after depth testing, alpha testing, TGSI_OPCODE_KILL_IF, etc.
*/
void
lp_build_mask_update(struct lp_build_mask_context *mask,
lp_build_loop_end_cond(state, end, step, LLVMIntNE);
}
+/**
+ * Creates a c-style for loop,
+ * contrasts lp_build_loop as this checks condition on entry
+ * e.g. for(i = start; i cmp_op end; i += step)
+ * \param state the for loop state, initialized here
+ * \param gallivm the gallivm state
+ * \param start starting value of iterator
+ * \param cmp_op comparison operator used for comparing current value with end value
+ * \param end value used to compare against iterator
+ * \param step value added to iterator at end of each loop
+ */
+void
+lp_build_for_loop_begin(struct lp_build_for_loop_state *state,
+ struct gallivm_state *gallivm,
+ LLVMValueRef start,
+ LLVMIntPredicate cmp_op,
+ LLVMValueRef end,
+ LLVMValueRef step)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+
+ assert(LLVMTypeOf(start) == LLVMTypeOf(end));
+ assert(LLVMTypeOf(start) == LLVMTypeOf(step));
+
+ state->begin = lp_build_insert_new_block(gallivm, "loop_begin");
+ state->step = step;
+ state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter");
+ state->gallivm = gallivm;
+ state->cond = cmp_op;
+ state->end = end;
+
+ LLVMBuildStore(builder, start, state->counter_var);
+ LLVMBuildBr(builder, state->begin);
+
+ LLVMPositionBuilderAtEnd(builder, state->begin);
+ state->counter = LLVMBuildLoad(builder, state->counter_var, "");
+
+ state->body = lp_build_insert_new_block(gallivm, "loop_body");
+ LLVMPositionBuilderAtEnd(builder, state->body);
+}
+
+/**
+ * End the for loop.
+ */
+void
+lp_build_for_loop_end(struct lp_build_for_loop_state *state)
+{
+ LLVMValueRef next, cond;
+ LLVMBuilderRef builder = state->gallivm->builder;
+
+ next = LLVMBuildAdd(builder, state->counter, state->step, "");
+ LLVMBuildStore(builder, next, state->counter_var);
+ LLVMBuildBr(builder, state->begin);
+
+ state->exit = lp_build_insert_new_block(state->gallivm, "loop_exit");
+
+ /*
+ * We build the comparison for the begin block here,
+ * if we build it earlier the output llvm ir is not human readable
+ * as the code produced is not in the standard begin -> body -> end order.
+ */
+ LLVMPositionBuilderAtEnd(builder, state->begin);
+ cond = LLVMBuildICmp(builder, state->cond, state->counter, state->end, "");
+ LLVMBuildCondBr(builder, cond, state->body, state->exit);
+
+ LLVMPositionBuilderAtEnd(builder, state->exit);
+}
/*
}
+static LLVMBuilderRef
+create_builder_at_entry(struct gallivm_state *gallivm)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
+ LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
+ LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
+ LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
+ LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
+
+ if (first_instr) {
+ LLVMPositionBuilderBefore(first_builder, first_instr);
+ } else {
+ LLVMPositionBuilderAtEnd(first_builder, first_block);
+ }
+
+ return first_builder;
+}
+
+
/**
* Allocate a scalar (or vector) variable.
*
const char *name)
{
LLVMBuilderRef builder = gallivm->builder;
- LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
- LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
- LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
- LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
- LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
+ LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
LLVMValueRef res;
- if (first_instr) {
- LLVMPositionBuilderBefore(first_builder, first_instr);
- } else {
- LLVMPositionBuilderAtEnd(first_builder, first_block);
- }
-
res = LLVMBuildAlloca(first_builder, type, name);
LLVMBuildStore(builder, LLVMConstNull(type), res);
}
+/**
+ * Like lp_build_alloca, but do not zero-initialize the variable.
+ */
+LLVMValueRef
+lp_build_alloca_undef(struct gallivm_state *gallivm,
+ LLVMTypeRef type,
+ const char *name)
+{
+ LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
+ LLVMValueRef res;
+
+ res = LLVMBuildAlloca(first_builder, type, name);
+
+ LLVMDisposeBuilder(first_builder);
+
+ return res;
+}
+
+
/**
* Allocate an array of scalars/vectors.
*
LLVMValueRef count,
const char *name)
{
- LLVMBuilderRef builder = gallivm->builder;
- LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
- LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
- LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
- LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
- LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
+ LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
LLVMValueRef res;
- if (first_instr) {
- LLVMPositionBuilderBefore(first_builder, first_instr);
- } else {
- LLVMPositionBuilderAtEnd(first_builder, first_block);
- }
-
res = LLVMBuildArrayAlloca(first_builder, type, count, name);
LLVMDisposeBuilder(first_builder);