LLVMValueRef addr[LP_MAX_TGSI_ADDRS][NUM_CHANNELS];
LLVMValueRef preds[LP_MAX_TGSI_PREDS][NUM_CHANNELS];
- /* we allocate an array of temps if we have indirect
- * addressing and then the temps above is unused */
+ /* We allocate/use this array of temps if (1 << TGSI_FILE_TEMPORARY) is
+ * set in the indirect_files field.
+ * The temps[] array above is unused then.
+ */
LLVMValueRef temps_array;
- boolean has_indirect_addressing;
+
+ /** bitmask indicating which register files are accessed indirectly */
+ unsigned indirect_files;
struct lp_build_mask_context *mask;
struct lp_exec_mask exec_mask;
/**
* Return pointer to a temporary register channel (src or dest).
+ * Note that indirect addressing cannot be handled here.
* \param index which temporary register
* \param chan which channel of the temp register.
- * \param is_indirect if true, add 'addr' to the index
- * \param addr indirect addressing offset (should already have been
- * multiplied by four).
*/
static LLVMValueRef
get_temp_ptr(struct lp_build_tgsi_soa_context *bld,
unsigned index,
- unsigned chan,
- boolean is_indirect,
- LLVMValueRef addr)
+ unsigned chan)
{
assert(chan < 4);
- if (bld->has_indirect_addressing) {
- LLVMValueRef lindex =
- LLVMConstInt(LLVMInt32Type(), index * 4 + chan, 0);
- if (is_indirect)
- lindex = lp_build_add(&bld->base, lindex, addr);
+ if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
+ LLVMValueRef lindex = lp_build_const_int32(index * 4 + chan);
return LLVMBuildGEP(bld->base.builder, bld->temps_array, &lindex, 1, "");
}
else {
}
+/**
+ * Read the current value of the ADDR register, convert the floats to
+ * ints, multiply by four and return the vector of offsets.
+ * The offsets will be used to index into the constant buffer or
+ * temporary register file.
+ */
+static LLVMValueRef
+get_indirect_offsets(struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_src_register *indirect_reg)
+{
+ /* always use X component of address register */
+ const int x = indirect_reg->SwizzleX;
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
+ uint swizzle = tgsi_util_get_src_register_swizzle(indirect_reg, x);
+ LLVMValueRef vec4 = lp_build_const_int_vec(bld->int_bld.type, 4);
+ LLVMValueRef addr_vec;
+
+ addr_vec = LLVMBuildLoad(bld->base.builder,
+ bld->addr[indirect_reg->Index][swizzle],
+ "load addr reg");
+
+ /* for indexing we want integers */
+ addr_vec = LLVMBuildFPToSI(bld->base.builder, addr_vec,
+ int_vec_type, "");
+
+ /* addr_vec = addr_vec * 4 */
+ addr_vec = lp_build_mul(&bld->int_bld, addr_vec, vec4);
+
+ return addr_vec;
+}
+
+
/**
* Register fetch.
*/
}
if (reg->Register.Indirect) {
- LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
- unsigned swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, chan_index );
-
- LLVMValueRef vec4 = lp_build_const_int_vec(bld->int_bld.type, 4);
-
- assert(bld->has_indirect_addressing);
-
- addr_vec = LLVMBuildLoad(bld->base.builder,
- bld->addr[reg->Indirect.Index][swizzle],
- "load addr");
-
- /* for indexing we want integers */
- addr_vec = LLVMBuildFPToSI(bld->base.builder, addr_vec,
- int_vec_type, "");
-
- /* addr_vec = addr_vec * 4 */
- addr_vec = lp_build_mul(&bld->base, addr_vec, vec4);
+ assert(bld->indirect_files);
+ addr_vec = get_indirect_offsets(bld, ®->Indirect);
}
switch (reg->Register.File) {
case TGSI_FILE_CONSTANT:
- {
- if (reg->Register.Indirect) {
- LLVMValueRef index_vec; /* index into the const buffer */
+ if (reg->Register.Indirect) {
+ LLVMValueRef index_vec; /* index into the const buffer */
- /* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
- index_vec = lp_build_const_int_vec(bld->int_bld.type,
- reg->Register.Index * 4 + swizzle);
+ assert(bld->indirect_files & (1 << TGSI_FILE_CONSTANT));
- /* index_vec = index_vec + addr_vec */
- index_vec = lp_build_add(&bld->base, index_vec, addr_vec);
+ /* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
+ index_vec = lp_build_const_int_vec(bld->int_bld.type,
+ reg->Register.Index * 4 + swizzle);
- /* Gather values from the constant buffer */
- res = build_gather(bld, bld->consts_ptr, index_vec);
- }
- else {
- LLVMValueRef index; /* index into the const buffer */
- LLVMValueRef scalar, scalar_ptr;
+ /* index_vec = index_vec + addr_vec */
+ index_vec = lp_build_add(&bld->int_bld, index_vec, addr_vec);
- index = lp_build_const_int32(reg->Register.Index*4 + swizzle);
+ /* Gather values from the constant buffer */
+ res = build_gather(bld, bld->consts_ptr, index_vec);
+ }
+ else {
+ LLVMValueRef index; /* index into the const buffer */
+ LLVMValueRef scalar, scalar_ptr;
- scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr,
- &index, 1, "");
- scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
+ index = lp_build_const_int32(reg->Register.Index*4 + swizzle);
- res = lp_build_broadcast_scalar(&bld->base, scalar);
- }
+ scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr,
+ &index, 1, "");
+ scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
+
+ res = lp_build_broadcast_scalar(&bld->base, scalar);
}
break;
break;
case TGSI_FILE_TEMPORARY:
- {
- LLVMValueRef addr = NULL;
- LLVMValueRef temp_ptr;
+ if (reg->Register.Indirect) {
+ LLVMValueRef vec_len =
+ lp_build_const_int_vec(bld->int_bld.type, bld->base.type.length);
+ LLVMValueRef index_vec; /* index into the const buffer */
+ LLVMValueRef temps_array;
+ LLVMTypeRef float4_ptr_type;
- if (reg->Register.Indirect) {
- LLVMValueRef zero = lp_build_const_int32(0);
- addr = LLVMBuildExtractElement(bld->base.builder,
- addr_vec, zero, "");
- }
+ assert(bld->indirect_files & (1 << TGSI_FILE_TEMPORARY));
+
+ /* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
+ index_vec = lp_build_const_int_vec(bld->int_bld.type,
+ reg->Register.Index * 4 + swizzle);
+
+ /* index_vec += addr_vec */
+ index_vec = lp_build_add(&bld->int_bld, index_vec, addr_vec);
+
+ /* index_vec *= vector_length */
+ index_vec = lp_build_mul(&bld->int_bld, index_vec, vec_len);
+
+ /* cast temps_array pointer to float* */
+ float4_ptr_type = LLVMPointerType(LLVMFloatType(), 0);
+ temps_array = LLVMBuildBitCast(bld->int_bld.builder, bld->temps_array,
+ float4_ptr_type, "");
- temp_ptr = get_temp_ptr(bld, reg->Register.Index,
- swizzle,
- reg->Register.Indirect,
- addr);
+ /* Gather values from the temporary register array */
+ res = build_gather(bld, temps_array, index_vec);
+ }
+ else {
+ LLVMValueRef temp_ptr;
+ temp_ptr = get_temp_ptr(bld, reg->Register.Index, swizzle);
res = LLVMBuildLoad(bld->base.builder, temp_ptr, "");
- if(!res)
+ if (!res)
return bld->base.undef;
}
break;
case TGSI_UTIL_SIGN_SET:
/* TODO: Use bitwese OR for floating point */
res = lp_build_abs( &bld->base, res );
- res = LLVMBuildNeg( bld->base.builder, res, "" );
- break;
-
+ /* fall through */
case TGSI_UTIL_SIGN_TOGGLE:
- res = LLVMBuildNeg( bld->base.builder, res, "" );
+ res = lp_build_negate( &bld->base, res );
break;
case TGSI_UTIL_SIGN_KEEP:
}
if (reg->Register.Indirect) {
+ /* XXX use get_indirect_offsets() here eventually */
LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
unsigned swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, chan_index );
+
+ assert(bld->indirect_files);
+
addr = LLVMBuildLoad(bld->base.builder,
bld->addr[reg->Indirect.Index][swizzle],
"");
addr = LLVMBuildExtractElement(bld->base.builder,
addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
"");
- addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
+ addr = LLVMBuildMul(bld->base.builder,
+ addr, LLVMConstInt(LLVMInt32Type(), 4, 0),
+ "");
}
switch( reg->Register.File ) {
bld->outputs[reg->Register.Index][chan_index]);
break;
- case TGSI_FILE_TEMPORARY: {
- LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
- chan_index,
- reg->Register.Indirect,
- addr);
- lp_exec_mask_store(&bld->exec_mask, pred, value, temp_ptr);
+ case TGSI_FILE_TEMPORARY:
+ if (reg->Register.Indirect) {
+ /* XXX not done yet */
+ debug_printf("WARNING: LLVM scatter store of temp regs"
+ " not implemented\n");
+ }
+ else {
+ LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
+ chan_index);
+ lp_exec_mask_store(&bld->exec_mask, pred, value, temp_ptr);
+ }
break;
- }
case TGSI_FILE_ADDRESS:
lp_exec_mask_store(&bld->exec_mask, pred, value,
case TGSI_FILE_PREDICATE:
lp_exec_mask_store(&bld->exec_mask, pred, value,
- bld->preds[index][chan_index]);
+ bld->preds[reg->Register.Index][chan_index]);
break;
default:
switch (decl->Declaration.File) {
case TGSI_FILE_TEMPORARY:
assert(idx < LP_MAX_TGSI_TEMPS);
- if (bld->has_indirect_addressing) {
+ if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
LLVMValueRef array_size = LLVMConstInt(LLVMInt32Type(),
last*4 + 4, 0);
bld->temps_array = lp_build_array_alloca(bld->base.builder,
bld.outputs = outputs;
bld.consts_ptr = consts_ptr;
bld.sampler = sampler;
- bld.has_indirect_addressing = info->opcode_count[TGSI_OPCODE_ARR] > 0 ||
- info->opcode_count[TGSI_OPCODE_ARL] > 0;
+ bld.indirect_files = info->indirect_files;
bld.instructions = (struct tgsi_full_instruction *)
MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) );
bld.max_instructions = LP_MAX_INSTRUCTIONS;