diff options
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_debug.h | 13 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_flow.c | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format_soa.c | 15 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_init.c | 18 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 228 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_type.c | 44 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_type.h | 4 |
7 files changed, 261 insertions, 63 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.h b/src/gallium/auxiliary/gallivm/lp_bld_debug.h index 1897acce79..858002b34f 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.h @@ -36,6 +36,19 @@ #include "util/u_string.h" +#define GALLIVM_DEBUG_TGSI 0x1 +#define GALLIVM_DEBUG_IR 0x2 +#define GALLIVM_DEBUG_ASM 0x4 +#define GALLIVM_DEBUG_NO_OPT 0x8 + + +#ifdef DEBUG +extern unsigned gallivm_debug; +#else +#define gallivm_debug 0 +#endif + + static INLINE void lp_build_name(LLVMValueRef val, const char *format, ...) { diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.c b/src/gallium/auxiliary/gallivm/lp_bld_flow.c index 560ce1de73..823a8ec7b7 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.c @@ -843,7 +843,7 @@ lp_build_alloca(LLVMBuilderRef builder, * 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 + * Also the scalarrepl pass is supposedly more powerful and can promote * arrays in many cases. * * See also: diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c index a2b0298a1c..e1b94adc85 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c @@ -89,6 +89,11 @@ lp_build_format_swizzle_soa(const struct util_format_description *format_desc, * It requires that a packed pixel fits into an element of the output * channels. The common case is when converting pixel with a depth of 32 bit or * less into floats. + * + * \param format_desc the format of the 'packed' incoming pixel vector + * \param type the desired type for rgba_out (type.length = n, above) + * \param packed the incoming vector of packed pixels + * \param rgba_out returns the SoA R,G,B,A vectors */ void lp_build_unpack_rgba_soa(LLVMBuilderRef builder, @@ -115,8 +120,8 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, /* Decode the input vector components */ start = 0; for (chan = 0; chan < format_desc->nr_channels; ++chan) { - unsigned width = format_desc->channel[chan].size; - unsigned stop = start + width; + const unsigned width = format_desc->channel[chan].size; + const unsigned stop = start + width; LLVMValueRef input; input = packed; @@ -247,9 +252,10 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, /** - * Fetch a pixel into a SoA. + * Fetch a texels from a texture, returning them in SoA layout. * - * \param type the desired return type for 'rgba' + * \param type the desired return type for 'rgba'. The vector length + * is the number of texels to fetch * * \param base_ptr points to start of the texture image block. For non- * compressed formats, this simply points to the texel. @@ -290,6 +296,7 @@ lp_build_fetch_rgba_soa(LLVMBuilderRef builder, /* * gather the texels from the texture + * Ex: packed = {BGRA, BGRA, BGRA, BGRA}. */ packed = lp_build_gather(builder, type.length, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c index 5067d0a164..bd080f397a 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -29,9 +29,23 @@ #include "pipe/p_compiler.h" #include "util/u_cpu_detect.h" #include "util/u_debug.h" +#include "lp_bld_debug.h" #include "lp_bld_init.h" +#ifdef DEBUG +unsigned gallivm_debug = 0; + +static const struct debug_named_value lp_bld_debug_flags[] = { + { "tgsi", GALLIVM_DEBUG_TGSI }, + { "ir", GALLIVM_DEBUG_IR }, + { "asm", GALLIVM_DEBUG_ASM }, + { "nopt", GALLIVM_DEBUG_NO_OPT }, + {NULL, 0} +}; +#endif + + LLVMModuleRef lp_build_module = NULL; LLVMExecutionEngineRef lp_build_engine = NULL; LLVMModuleProviderRef lp_build_provider = NULL; @@ -41,6 +55,10 @@ LLVMTargetDataRef lp_build_target = NULL; void lp_build_init(void) { +#ifdef DEBUG + gallivm_debug = debug_get_flags_option("GALLIVM_DEBUG", lp_bld_debug_flags, 0 ); +#endif + LLVMInitializeNativeTarget(); LLVMLinkInJIT(); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index aaf3360aa2..40ea94c493 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -81,6 +81,8 @@ #define QUAD_BOTTOM_LEFT 2 #define QUAD_BOTTOM_RIGHT 3 +#define LP_MAX_INSTRUCTIONS 256 + struct lp_exec_mask { struct lp_build_context *bld; @@ -105,6 +107,13 @@ struct lp_exec_mask { } loop_stack[LP_MAX_TGSI_NESTING]; int loop_stack_size; + LLVMValueRef ret_mask; + struct { + int pc; + LLVMValueRef ret_mask; + } call_stack[LP_MAX_TGSI_NESTING]; + int call_stack_size; + LLVMValueRef exec_mask; }; @@ -134,6 +143,9 @@ struct lp_build_tgsi_soa_context struct lp_build_mask_context *mask; struct lp_exec_mask exec_mask; + + struct tgsi_full_instruction *instructions; + uint max_instructions; }; static const unsigned char @@ -166,9 +178,10 @@ static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context mask->has_mask = FALSE; mask->cond_stack_size = 0; mask->loop_stack_size = 0; + mask->call_stack_size = 0; mask->int_vec_type = lp_build_int_vec_type(mask->bld->type); - mask->break_mask = mask->cont_mask = mask->cond_mask = + mask->exec_mask = mask->ret_mask = mask->break_mask = mask->cont_mask = mask->cond_mask = LLVMConstAllOnes(mask->int_vec_type); } @@ -189,9 +202,16 @@ static void lp_exec_mask_update(struct lp_exec_mask *mask) } else mask->exec_mask = mask->cond_mask; + if (mask->call_stack_size) { + mask->exec_mask = LLVMBuildAnd(mask->bld->builder, + mask->exec_mask, + mask->ret_mask, + "callmask"); + } mask->has_mask = (mask->cond_stack_size > 0 || - mask->loop_stack_size > 0); + mask->loop_stack_size > 0 || + mask->call_stack_size > 0); } static void lp_exec_mask_cond_push(struct lp_exec_mask *mask, @@ -368,6 +388,49 @@ static void lp_exec_mask_store(struct lp_exec_mask *mask, LLVMBuildStore(mask->bld->builder, val, dst); } +static void lp_exec_mask_call(struct lp_exec_mask *mask, + int func, + int *pc) +{ + assert(mask->call_stack_size < LP_MAX_TGSI_NESTING); + mask->call_stack[mask->call_stack_size].pc = *pc; + mask->call_stack[mask->call_stack_size].ret_mask = mask->ret_mask; + mask->call_stack_size++; + *pc = func; +} + +static void lp_exec_mask_ret(struct lp_exec_mask *mask, int *pc) +{ + LLVMValueRef exec_mask; + + if (mask->call_stack_size == 0) { + /* returning from main() */ + *pc = -1; + return; + } + exec_mask = LLVMBuildNot(mask->bld->builder, + mask->exec_mask, + "ret"); + + mask->ret_mask = LLVMBuildAnd(mask->bld->builder, + mask->ret_mask, + exec_mask, "ret_full"); + + lp_exec_mask_update(mask); +} + +static void lp_exec_mask_bgnsub(struct lp_exec_mask *mask) +{ +} + +static void lp_exec_mask_endsub(struct lp_exec_mask *mask, int *pc) +{ + assert(mask->call_stack_size); + mask->call_stack_size--; + *pc = mask->call_stack[mask->call_stack_size].pc; + mask->ret_mask = mask->call_stack[mask->call_stack_size].ret_mask; + lp_exec_mask_update(mask); +} static LLVMValueRef emit_ddx(struct lp_build_tgsi_soa_context *bld, @@ -418,34 +481,36 @@ emit_fetch( const unsigned chan_index ) { const struct tgsi_full_src_register *reg = &inst->Src[index]; - unsigned swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index ); + const unsigned swizzle = + tgsi_util_get_full_src_register_swizzle(reg, chan_index); LLVMValueRef res; LLVMValueRef addr = NULL; - switch (swizzle) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - - 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 ); - addr = LLVMBuildLoad(bld->base.builder, - bld->addr[reg->Indirect.Index][swizzle], - ""); - /* for indexing we want integers */ - addr = LLVMBuildFPToSI(bld->base.builder, addr, - int_vec_type, ""); - addr = LLVMBuildExtractElement(bld->base.builder, - addr, LLVMConstInt(LLVMInt32Type(), 0, 0), - ""); - addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0)); - } - - switch (reg->Register.File) { - case TGSI_FILE_CONSTANT: { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), reg->Register.Index*4 + swizzle, 0); + if (swizzle > 3) { + assert(0 && "invalid swizzle in emit_fetch()"); + return bld->base.undef; + } + + 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 ); + addr = LLVMBuildLoad(bld->base.builder, + bld->addr[reg->Indirect.Index][swizzle], + ""); + /* for indexing we want integers */ + addr = LLVMBuildFPToSI(bld->base.builder, addr, + int_vec_type, ""); + addr = LLVMBuildExtractElement(bld->base.builder, + addr, LLVMConstInt(LLVMInt32Type(), 0, 0), + ""); + addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0)); + } + + switch (reg->Register.File) { + case TGSI_FILE_CONSTANT: + { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), + reg->Register.Index*4 + swizzle, 0); LLVMValueRef scalar, scalar_ptr; if (reg->Register.Indirect) { @@ -453,24 +518,26 @@ emit_fetch( "\taddr = %d\n", addr);*/ index = lp_build_add(&bld->base, index, addr); } - scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr, &index, 1, ""); + 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_IMMEDIATE: - res = bld->immediates[reg->Register.Index][swizzle]; - assert(res); - break; + case TGSI_FILE_IMMEDIATE: + res = bld->immediates[reg->Register.Index][swizzle]; + assert(res); + break; - case TGSI_FILE_INPUT: - res = bld->inputs[reg->Register.Index][swizzle]; - assert(res); - break; + case TGSI_FILE_INPUT: + res = bld->inputs[reg->Register.Index][swizzle]; + assert(res); + break; - case TGSI_FILE_TEMPORARY: { + case TGSI_FILE_TEMPORARY: + { LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index, swizzle, reg->Register.Indirect, @@ -478,17 +545,11 @@ emit_fetch( res = LLVMBuildLoad(bld->base.builder, temp_ptr, ""); if(!res) return bld->base.undef; - break; - } - - default: - assert( 0 ); - return bld->base.undef; } break; default: - assert( 0 ); + assert(0 && "invalid src register in emit_fetch()"); return bld->base.undef; } @@ -892,10 +953,10 @@ emit_declaration( case TGSI_FILE_TEMPORARY: assert(idx < LP_MAX_TGSI_TEMPS); if (bld->has_indirect_addressing) { - LLVMValueRef val = LLVMConstInt(LLVMInt32Type(), - last*4 + 4, 0); + LLVMValueRef array_size = LLVMConstInt(LLVMInt32Type(), + last*4 + 4, 0); bld->temps_array = lp_build_array_alloca(bld->base.builder, - vec_type, val, ""); + vec_type, array_size, ""); } else { for (i = 0; i < NUM_CHANNELS; i++) bld->temps[idx][i] = lp_build_alloca(bld->base.builder, @@ -939,7 +1000,8 @@ static boolean emit_instruction( struct lp_build_tgsi_soa_context *bld, const struct tgsi_full_instruction *inst, - const struct tgsi_opcode_info *info) + const struct tgsi_opcode_info *info, + int *pc) { unsigned chan_index; LLVMValueRef src0, src1, src2; @@ -963,6 +1025,8 @@ emit_instruction( * redundant code. */ + (*pc)++; + assert(info->num_dst <= 1); if (info->num_dst) { FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { @@ -1561,16 +1625,18 @@ emit_instruction( break; case TGSI_OPCODE_CAL: - /* FIXME */ - return FALSE; + lp_exec_mask_call(&bld->exec_mask, + inst->Label.Label, + pc); + break; case TGSI_OPCODE_RET: - /* FIXME */ - return FALSE; + lp_exec_mask_ret(&bld->exec_mask, pc); break; case TGSI_OPCODE_END: + *pc = -1; break; case TGSI_OPCODE_SSG: @@ -1736,6 +1802,10 @@ emit_instruction( lp_exec_bgnloop(&bld->exec_mask); break; + case TGSI_OPCODE_BGNSUB: + lp_exec_mask_bgnsub(&bld->exec_mask); + break; + case TGSI_OPCODE_ELSE: lp_exec_mask_cond_invert(&bld->exec_mask); break; @@ -1748,6 +1818,10 @@ emit_instruction( lp_exec_endloop(&bld->exec_mask); break; + case TGSI_OPCODE_ENDSUB: + lp_exec_mask_endsub(&bld->exec_mask, pc); + break; + case TGSI_OPCODE_PUSHA: /* deprecated? */ assert(0); @@ -1888,7 +1962,9 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, struct lp_build_tgsi_soa_context bld; struct tgsi_parse_context parse; uint num_immediates = 0; + uint num_instructions = 0; unsigned i; + int pc = 0; /* Setup build context */ memset(&bld, 0, sizeof bld); @@ -1902,6 +1978,13 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, bld.sampler = sampler; bld.has_indirect_addressing = info->opcode_count[TGSI_OPCODE_ARR] > 0 || info->opcode_count[TGSI_OPCODE_ARL] > 0; + bld.instructions = (struct tgsi_full_instruction *) + MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) ); + bld.max_instructions = LP_MAX_INSTRUCTIONS; + + if (!bld.instructions) { + return; + } lp_exec_mask_init(&bld.exec_mask, &bld.base); @@ -1918,11 +2001,21 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, case TGSI_TOKEN_TYPE_INSTRUCTION: { - unsigned opcode = parse.FullToken.FullInstruction.Instruction.Opcode; - const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(opcode); - if (!emit_instruction( &bld, &parse.FullToken.FullInstruction, opcode_info )) - _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n", - opcode_info->mnemonic); + /* save expanded instruction */ + if (num_instructions == bld.max_instructions) { + bld.instructions = REALLOC(bld.instructions, + bld.max_instructions + * sizeof(struct tgsi_full_instruction), + (bld.max_instructions + LP_MAX_INSTRUCTIONS) + * sizeof(struct tgsi_full_instruction)); + bld.max_instructions += LP_MAX_INSTRUCTIONS; + } + + memcpy(bld.instructions + num_instructions, + &parse.FullToken.FullInstruction, + sizeof(bld.instructions[0])); + + num_instructions++; } break; @@ -1949,6 +2042,16 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, assert( 0 ); } } + + while (pc != -1) { + struct tgsi_full_instruction *instr = bld.instructions + pc; + const struct tgsi_opcode_info *opcode_info = + tgsi_get_opcode_info(instr->Instruction.Opcode); + if (!emit_instruction( &bld, instr, opcode_info, &pc )) + _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n", + opcode_info->mnemonic); + } + if (0) { LLVMBasicBlockRef block = LLVMGetInsertBlock(builder); LLVMValueRef function = LLVMGetBasicBlockParent(block); @@ -1958,5 +2061,14 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, debug_printf("2222222222222222222222222222 \n"); } tgsi_parse_free( &parse ); + + if (0) { + LLVMModuleRef module = LLVMGetGlobalParent( + LLVMGetBasicBlockParent(LLVMGetInsertBlock(bld.base.builder))); + LLVMDumpModule(module); + + } + + FREE( bld.instructions ); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.c b/src/gallium/auxiliary/gallivm/lp_bld_type.c index 37d278d237..aac3a57bc7 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.c @@ -195,6 +195,7 @@ lp_uint_type(struct lp_type type) { struct lp_type res_type; + assert(type.length <= LP_MAX_VECTOR_LENGTH); memset(&res_type, 0, sizeof res_type); res_type.width = type.width; res_type.length = type.length; @@ -211,6 +212,7 @@ lp_int_type(struct lp_type type) { struct lp_type res_type; + assert(type.length <= LP_MAX_VECTOR_LENGTH); memset(&res_type, 0, sizeof res_type); res_type.width = type.width; res_type.length = type.length; @@ -239,6 +241,43 @@ lp_wider_type(struct lp_type type) /** + * Return the size of the LLVMType in bits. + * XXX this function doesn't necessarily handle all LLVM types. + */ +unsigned +lp_sizeof_llvm_type(LLVMTypeRef t) +{ + LLVMTypeKind k = LLVMGetTypeKind(t); + + switch (k) { + case LLVMIntegerTypeKind: + return LLVMGetIntTypeWidth(t); + case LLVMFloatTypeKind: + return 8 * sizeof(float); + case LLVMDoubleTypeKind: + return 8 * sizeof(double); + case LLVMVectorTypeKind: + { + LLVMTypeRef elem = LLVMGetElementType(t); + unsigned len = LLVMGetVectorSize(t); + return len * lp_sizeof_llvm_type(elem); + } + break; + case LLVMArrayTypeKind: + { + LLVMTypeRef elem = LLVMGetElementType(t); + unsigned len = LLVMGetArrayLength(t); + return len * lp_sizeof_llvm_type(elem); + } + break; + default: + assert(0 && "Unexpected type in lp_get_llvm_type_size()"); + return 0; + } +} + + +/** * Return string name for a LLVMTypeKind. Useful for debugging. */ const char * @@ -315,6 +354,11 @@ lp_dump_llvmtype(LLVMTypeRef t) unsigned b = LLVMGetIntTypeWidth(t); debug_printf("%u-bit Integer\n", b); } + else if (k == LLVMPointerTypeKind) { + LLVMTypeRef te = LLVMGetElementType(t); + debug_printf("Pointer to "); + lp_dump_llvmtype(te); + } else { debug_printf("%s\n", lp_typekind_name(k)); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.h b/src/gallium/auxiliary/gallivm/lp_bld_type.h index b3f9e9175d..17819d4d32 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.h @@ -316,6 +316,10 @@ struct lp_type lp_wider_type(struct lp_type type); +unsigned +lp_sizeof_llvm_type(LLVMTypeRef t); + + const char * lp_typekind_name(LLVMTypeKind t); |