int main() { LLVMContextRef context = LLVMGetGlobalContext(); LLVMModuleRef module = LLVMModuleCreateWithName("test-101"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInt32Type() // LLVMFunctionType(rtnType, paramType, parmCnt, isVarArg) // LLVMAddFunction(module, name, functionType) LLVMTypeRef main = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0); LLVMValueRef mainFn = LLVMAddFunction(module, "main", main); LLVMBasicBlockRef mainBlk = LLVMAppendBasicBlock(mainFn, "entry"); LLVMPositionBuilderAtEnd(builder, mainBlk); LLVMValueRef str = LLVMBuildGlobalStringPtr(builder, "Hello World!", "str"); LLVMTypeRef args[1]; args[0] = LLVMPointerType(LLVMInt8Type(), 0); LLVMTypeRef puts = LLVMFunctionType(LLVMInt32Type(), args, 1, 0); LLVMValueRef putsFn = LLVMAddFunction(module, "puts", puts); LLVMBuildCall(builder, putsFn, &str, 1, ""); LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 0, 0)); LLVMDumpModule(module); return 0; }
void vm_state_destroy(struct vm_state *vm) { LLVMBasicBlockRef current_block, return_block; char *error; current_block = LLVMGetInsertBlock(vm->builder); return_block = LLVMInsertBasicBlock(current_block, "ret"); LLVMPositionBuilderAtEnd(vm->builder, current_block); LLVMBuildBr(vm->builder, return_block); LLVMPositionBuilderAtEnd(vm->builder, return_block); LLVMBuildRetVoid(vm->builder); LLVMMoveBasicBlockAfter(return_block, current_block); LLVMDumpModule(vm->module); error = NULL; LLVMVerifyModule(vm->module, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMDisposeBuilder(vm->builder); LLVMDisposeModule(vm->module); symbol_table_destroy(vm->symtab); }
int main (void) { LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInitializeNativeTarget(); LLVMTypeRef funcType = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0); LLVMValueRef func = LLVMAddFunction(module, "main", funcType); LLVMSetLinkage(func, LLVMExternalLinkage); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMPositionBuilderAtEnd(builder, block); LLVMValueRef cond = LLVMBuildICmp(builder, LLVMIntNE, LLVMConstInt(LLVMInt32Type(), 2, 0), LLVMConstInt(LLVMInt32Type(), 1, 0), "ifcond"); LLVMValueRef owning_block = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); //TODO: WRONG?? //LLVMValueRef owning_block = LLVMBasicBlockAsValue(LLVMGetPreviousBasicBlock(LLVMGetInsertBlock(builder))); // 2. Generate new blocks for cases. LLVMBasicBlockRef then_ref = LLVMAppendBasicBlock(owning_block, "then"); LLVMBasicBlockRef else_ref = LLVMAppendBasicBlock(owning_block, "else"); LLVMBasicBlockRef merge_ref = LLVMAppendBasicBlock(owning_block, "ifmerge"); // 3. Branch conditionally on then or else. LLVMBuildCondBr(builder, cond, then_ref, else_ref); // 4. Build then branch prologue. LLVMPositionBuilderAtEnd(builder, then_ref); LLVMValueRef hi1 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp"); // 5. Connect then branch to merge block. LLVMBuildBr(builder, merge_ref); then_ref = LLVMGetInsertBlock(builder); // 6. Build else branch prologue. LLVMPositionBuilderAtEnd(builder, else_ref); LLVMValueRef hi2 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp2"); // 7. Connect else branch to merge block. LLVMBuildBr(builder, merge_ref); else_ref = LLVMGetInsertBlock(builder); // 8. Position ourselves after the merge block. LLVMPositionBuilderAtEnd(builder, merge_ref); // 9. Build the phi node. // LLVMValueRef phi = LLVMBuildPhi(builder, LLVMDoubleType(), "phi"); // 10. Add incoming edges. // LLVMAddIncoming(phi, &hi1, &then_ref, 1); // LLVMAddIncoming(phi, &hi2, &else_ref, 1); LLVMDumpModule(module); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); return 0; }
int LLVM_execute(LLVMCompiledProgram program) { LLVMModuleRef module = program.module; LLVMValueRef function = program.function; char *error = NULL; // Used to retrieve messages from functions LLVMExecutionEngineRef engine; LLVMModuleProviderRef provider = LLVMCreateModuleProviderForExistingModule(module); error = NULL; if(LLVMCreateJITCompiler(&engine, provider, 2, &error) != 0) { fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); abort(); } LLVMPassManagerRef pass = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); LLVMAddPromoteMemoryToRegisterPass(pass); LLVMAddGVNPass(pass); LLVMAddCFGSimplificationPass(pass); LLVMRunPassManager(pass, module); #ifdef NDEBUG #else LLVMDumpModule(module); #endif LLVMGenericValueRef exec_args[] = {}; LLVMGenericValueRef exec_res = LLVMRunFunction(engine, function, 0, exec_args); int result = LLVMGenericValueToInt(exec_res, 0); LLVMDisposePassManager(pass); LLVMDisposeExecutionEngine(engine); return result; }
unsigned r600_llvm_compile( LLVMModuleRef mod, enum radeon_family family, struct r600_bytecode *bc, boolean *use_kill, unsigned dump, struct pipe_debug_callback *debug) { unsigned r; struct radeon_shader_binary binary; const char * gpu_family = r600_get_llvm_processor_name(family); radeon_shader_binary_init(&binary); if (dump) LLVMDumpModule(mod); r = radeon_llvm_compile(mod, &binary, gpu_family, NULL, debug); r = r600_create_shader(bc, &binary, use_kill); radeon_shader_binary_clean(&binary); return r; }
void lp_build_tgsi_aos(struct gallivm_state *gallivm, const struct tgsi_token *tokens, struct lp_type type, const unsigned char swizzles[4], LLVMValueRef consts_ptr, const LLVMValueRef *inputs, LLVMValueRef *outputs, struct lp_build_sampler_aos *sampler, const struct tgsi_shader_info *info) { struct lp_build_tgsi_aos_context bld; struct tgsi_parse_context parse; uint num_immediates = 0; unsigned chan; int pc = 0; /* Setup build context */ memset(&bld, 0, sizeof bld); lp_build_context_init(&bld.bld_base.base, gallivm, type); lp_build_context_init(&bld.bld_base.uint_bld, gallivm, lp_uint_type(type)); lp_build_context_init(&bld.bld_base.int_bld, gallivm, lp_int_type(type)); lp_build_context_init(&bld.int_bld, gallivm, lp_int_type(type)); for (chan = 0; chan < 4; ++chan) { bld.swizzles[chan] = swizzles[chan]; bld.inv_swizzles[swizzles[chan]] = chan; } bld.inputs = inputs; bld.outputs = outputs; bld.consts_ptr = consts_ptr; bld.sampler = sampler; bld.indirect_files = info->indirect_files; bld.bld_base.emit_swizzle = swizzle_aos; bld.bld_base.info = info; bld.bld_base.emit_fetch_funcs[TGSI_FILE_CONSTANT] = emit_fetch_constant; bld.bld_base.emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate; bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input; bld.bld_base.emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary; /* Set opcode actions */ lp_set_default_actions_cpu(&bld.bld_base); if (!lp_bld_tgsi_list_init(&bld.bld_base)) { return; } tgsi_parse_init(&parse, tokens); while (!tgsi_parse_end_of_tokens(&parse)) { tgsi_parse_token(&parse); switch(parse.FullToken.Token.Type) { case TGSI_TOKEN_TYPE_DECLARATION: /* Inputs already interpolated */ lp_emit_declaration_aos(&bld, &parse.FullToken.FullDeclaration); break; case TGSI_TOKEN_TYPE_INSTRUCTION: /* save expanded instruction */ lp_bld_tgsi_add_instruction(&bld.bld_base, &parse.FullToken.FullInstruction); break; case TGSI_TOKEN_TYPE_IMMEDIATE: /* simply copy the immediate values into the next immediates[] slot */ { const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; float imm[4]; assert(size <= 4); assert(num_immediates < LP_MAX_TGSI_IMMEDIATES); for (chan = 0; chan < 4; ++chan) { imm[chan] = 0.0f; } for (chan = 0; chan < size; ++chan) { unsigned swizzle = bld.swizzles[chan]; imm[swizzle] = parse.FullToken.FullImmediate.u[chan].Float; } bld.immediates[num_immediates] = lp_build_const_aos(gallivm, type, imm[0], imm[1], imm[2], imm[3], NULL); num_immediates++; } break; case TGSI_TOKEN_TYPE_PROPERTY: break; default: assert(0); } } while (pc != -1) { struct tgsi_full_instruction *instr = bld.bld_base.instructions + pc; const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(instr->Instruction.Opcode); if (!lp_emit_instruction_aos(&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(gallivm->builder); LLVMValueRef function = LLVMGetBasicBlockParent(block); debug_printf("11111111111111111111111111111 \n"); tgsi_dump(tokens, 0); lp_debug_dump_value(function); debug_printf("2222222222222222222222222222 \n"); } tgsi_parse_free(&parse); FREE(bld.bld_base.instructions); if (0) { LLVMModuleRef module = LLVMGetGlobalParent( LLVMGetBasicBlockParent(LLVMGetInsertBlock(gallivm->builder))); LLVMDumpModule(module); } }
/** * Compile an LLVM module to machine code. * * @returns 0 for success, 1 for failure */ unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary, const char *gpu_family, unsigned dump, LLVMTargetMachineRef tm) { char cpu[CPU_STRING_LEN]; char fs[FS_STRING_LEN]; char *err; bool dispose_tm = false; LLVMContextRef llvm_ctx; unsigned rval = 0; LLVMMemoryBufferRef out_buffer; unsigned buffer_size; const char *buffer_data; char triple[TRIPLE_STRING_LEN]; LLVMBool mem_err; if (!tm) { strncpy(triple, "r600--", TRIPLE_STRING_LEN); LLVMTargetRef target = radeon_llvm_get_r600_target(triple); if (!target) { return 1; } strncpy(cpu, gpu_family, CPU_STRING_LEN); memset(fs, 0, sizeof(fs)); if (dump) { strncpy(fs, "+DumpCode", FS_STRING_LEN); } tm = LLVMCreateTargetMachine(target, triple, cpu, fs, LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault); dispose_tm = true; } if (dump) { LLVMDumpModule(M); } /* Setup Diagnostic Handler*/ llvm_ctx = LLVMGetModuleContext(M); #if HAVE_LLVM >= 0x0305 LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &rval); #endif rval = 0; /* Compile IR*/ mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, &out_buffer); /* Process Errors/Warnings */ if (mem_err) { fprintf(stderr, "%s: %s", __FUNCTION__, err); FREE(err); LLVMDisposeTargetMachine(tm); return 1; } if (0 != rval) { fprintf(stderr, "%s: Processing Diag Flag\n", __FUNCTION__); } /* Extract Shader Code*/ buffer_size = LLVMGetBufferSize(out_buffer); buffer_data = LLVMGetBufferStart(out_buffer); radeon_elf_read(buffer_data, buffer_size, binary, dump); /* Clean up */ LLVMDisposeMemoryBuffer(out_buffer); if (dispose_tm) { LLVMDisposeTargetMachine(tm); } return rval; }
SCM llvm_dump_module(SCM scm_self) { struct llvm_module_t *self = get_llvm(scm_self); LLVMDumpModule(self->module); return SCM_UNSPECIFIED; }
static void lp_jit_create_types(struct lp_fragment_shader_variant *lp) { struct gallivm_state *gallivm = lp->gallivm; LLVMContextRef lc = gallivm->context; LLVMTypeRef viewport_type, texture_type, sampler_type; /* struct lp_jit_viewport */ { LLVMTypeRef elem_types[LP_JIT_VIEWPORT_NUM_FIELDS]; elem_types[LP_JIT_VIEWPORT_MIN_DEPTH] = elem_types[LP_JIT_VIEWPORT_MAX_DEPTH] = LLVMFloatTypeInContext(lc); viewport_type = LLVMStructTypeInContext(lc, elem_types, Elements(elem_types), 0); LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, min_depth, gallivm->target, viewport_type, LP_JIT_VIEWPORT_MIN_DEPTH); LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, max_depth, gallivm->target, viewport_type, LP_JIT_VIEWPORT_MAX_DEPTH); LP_CHECK_STRUCT_SIZE(struct lp_jit_viewport, gallivm->target, viewport_type); } /* struct lp_jit_texture */ { LLVMTypeRef elem_types[LP_JIT_TEXTURE_NUM_FIELDS]; elem_types[LP_JIT_TEXTURE_WIDTH] = elem_types[LP_JIT_TEXTURE_HEIGHT] = elem_types[LP_JIT_TEXTURE_DEPTH] = elem_types[LP_JIT_TEXTURE_FIRST_LEVEL] = elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32TypeInContext(lc); elem_types[LP_JIT_TEXTURE_BASE] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0); elem_types[LP_JIT_TEXTURE_ROW_STRIDE] = elem_types[LP_JIT_TEXTURE_IMG_STRIDE] = elem_types[LP_JIT_TEXTURE_MIP_OFFSETS] = LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TEXTURE_LEVELS); texture_type = LLVMStructTypeInContext(lc, elem_types, Elements(elem_types), 0); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, width, gallivm->target, texture_type, LP_JIT_TEXTURE_WIDTH); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, height, gallivm->target, texture_type, LP_JIT_TEXTURE_HEIGHT); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, depth, gallivm->target, texture_type, LP_JIT_TEXTURE_DEPTH); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, first_level, gallivm->target, texture_type, LP_JIT_TEXTURE_FIRST_LEVEL); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, last_level, gallivm->target, texture_type, LP_JIT_TEXTURE_LAST_LEVEL); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, base, gallivm->target, texture_type, LP_JIT_TEXTURE_BASE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, row_stride, gallivm->target, texture_type, LP_JIT_TEXTURE_ROW_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, img_stride, gallivm->target, texture_type, LP_JIT_TEXTURE_IMG_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, mip_offsets, gallivm->target, texture_type, LP_JIT_TEXTURE_MIP_OFFSETS); LP_CHECK_STRUCT_SIZE(struct lp_jit_texture, gallivm->target, texture_type); } /* struct lp_jit_sampler */ { LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS]; elem_types[LP_JIT_SAMPLER_MIN_LOD] = elem_types[LP_JIT_SAMPLER_MAX_LOD] = elem_types[LP_JIT_SAMPLER_LOD_BIAS] = LLVMFloatTypeInContext(lc); elem_types[LP_JIT_SAMPLER_BORDER_COLOR] = LLVMArrayType(LLVMFloatTypeInContext(lc), 4); sampler_type = LLVMStructTypeInContext(lc, elem_types, Elements(elem_types), 0); LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod, gallivm->target, sampler_type, LP_JIT_SAMPLER_MIN_LOD); LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod, gallivm->target, sampler_type, LP_JIT_SAMPLER_MAX_LOD); LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias, gallivm->target, sampler_type, LP_JIT_SAMPLER_LOD_BIAS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color, gallivm->target, sampler_type, LP_JIT_SAMPLER_BORDER_COLOR); LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler, gallivm->target, sampler_type); } /* struct lp_jit_context */ { LLVMTypeRef elem_types[LP_JIT_CTX_COUNT]; LLVMTypeRef context_type; elem_types[LP_JIT_CTX_CONSTANTS] = LLVMArrayType(LLVMPointerType(LLVMFloatTypeInContext(lc), 0), LP_MAX_TGSI_CONST_BUFFERS); elem_types[LP_JIT_CTX_NUM_CONSTANTS] = LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TGSI_CONST_BUFFERS); elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc); elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc); elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0); elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0); elem_types[LP_JIT_CTX_VIEWPORTS] = LLVMPointerType(viewport_type, 0); elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type, PIPE_MAX_SHADER_SAMPLER_VIEWS); elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type, PIPE_MAX_SAMPLERS); context_type = LLVMStructTypeInContext(lc, elem_types, Elements(elem_types), 0); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants, gallivm->target, context_type, LP_JIT_CTX_CONSTANTS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, num_constants, gallivm->target, context_type, LP_JIT_CTX_NUM_CONSTANTS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value, gallivm->target, context_type, LP_JIT_CTX_ALPHA_REF); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front, gallivm->target, context_type, LP_JIT_CTX_STENCIL_REF_FRONT); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back, gallivm->target, context_type, LP_JIT_CTX_STENCIL_REF_BACK); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, u8_blend_color, gallivm->target, context_type, LP_JIT_CTX_U8_BLEND_COLOR); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, f_blend_color, gallivm->target, context_type, LP_JIT_CTX_F_BLEND_COLOR); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, viewports, gallivm->target, context_type, LP_JIT_CTX_VIEWPORTS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures, gallivm->target, context_type, LP_JIT_CTX_TEXTURES); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers, gallivm->target, context_type, LP_JIT_CTX_SAMPLERS); LP_CHECK_STRUCT_SIZE(struct lp_jit_context, gallivm->target, context_type); lp->jit_context_ptr_type = LLVMPointerType(context_type, 0); } /* struct lp_jit_thread_data */ { LLVMTypeRef elem_types[LP_JIT_THREAD_DATA_COUNT]; LLVMTypeRef thread_data_type; elem_types[LP_JIT_THREAD_DATA_COUNTER] = LLVMInt64TypeInContext(lc); elem_types[LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX] = LLVMInt32TypeInContext(lc); thread_data_type = LLVMStructTypeInContext(lc, elem_types, Elements(elem_types), 0); lp->jit_thread_data_ptr_type = LLVMPointerType(thread_data_type, 0); } if (gallivm_debug & GALLIVM_DEBUG_IR) { LLVMDumpModule(gallivm->module); } }
ALIGN_STACK static boolean test_one(unsigned verbose, FILE *fp, const struct pipe_blend_state *blend, enum vector_mode mode, struct lp_type type) { LLVMModuleRef module = NULL; LLVMValueRef func = NULL; LLVMExecutionEngineRef engine = NULL; LLVMModuleProviderRef provider = NULL; LLVMPassManagerRef pass = NULL; char *error = NULL; blend_test_ptr_t blend_test_ptr; boolean success; const unsigned n = LP_TEST_NUM_SAMPLES; int64_t cycles[LP_TEST_NUM_SAMPLES]; double cycles_avg = 0.0; unsigned i, j; if(verbose >= 1) dump_blend_type(stdout, blend, mode, type); module = LLVMModuleCreateWithName("test"); func = add_blend_test(module, blend, mode, type); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { LLVMDumpModule(module); abort(); } LLVMDisposeMessage(error); provider = LLVMCreateModuleProviderForExistingModule(module); if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) { if(verbose < 1) dump_blend_type(stderr, blend, mode, type); fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); abort(); } #if 0 pass = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, * but there are more on SVN. */ LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); LLVMAddPromoteMemoryToRegisterPass(pass); LLVMAddGVNPass(pass); LLVMAddCFGSimplificationPass(pass); LLVMRunPassManager(pass, module); #else (void)pass; #endif if(verbose >= 2) LLVMDumpModule(module); blend_test_ptr = (blend_test_ptr_t)LLVMGetPointerToGlobal(engine, func); if(verbose >= 2) lp_disassemble(blend_test_ptr); success = TRUE; for(i = 0; i < n && success; ++i) { if(mode == AoS) { ALIGN16_ATTRIB uint8_t src[LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t con[LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t res[LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8]; int64_t start_counter = 0; int64_t end_counter = 0; random_vec(type, src); random_vec(type, dst); random_vec(type, con); { double fsrc[LP_MAX_VECTOR_LENGTH]; double fdst[LP_MAX_VECTOR_LENGTH]; double fcon[LP_MAX_VECTOR_LENGTH]; double fref[LP_MAX_VECTOR_LENGTH]; read_vec(type, src, fsrc); read_vec(type, dst, fdst); read_vec(type, con, fcon); for(j = 0; j < type.length; j += 4) compute_blend_ref(blend, fsrc + j, fdst + j, fcon + j, fref + j); write_vec(type, ref, fref); } start_counter = rdtsc(); blend_test_ptr(src, dst, con, res); end_counter = rdtsc(); cycles[i] = end_counter - start_counter; if(!compare_vec(type, res, ref)) { success = FALSE; if(verbose < 1) dump_blend_type(stderr, blend, mode, type); fprintf(stderr, "MISMATCH\n"); fprintf(stderr, " Src: "); dump_vec(stderr, type, src); fprintf(stderr, "\n"); fprintf(stderr, " Dst: "); dump_vec(stderr, type, dst); fprintf(stderr, "\n"); fprintf(stderr, " Con: "); dump_vec(stderr, type, con); fprintf(stderr, "\n"); fprintf(stderr, " Res: "); dump_vec(stderr, type, res); fprintf(stderr, "\n"); fprintf(stderr, " Ref: "); dump_vec(stderr, type, ref); fprintf(stderr, "\n"); } } if(mode == SoA) { const unsigned stride = type.length*type.width/8; ALIGN16_ATTRIB uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8]; ALIGN16_ATTRIB uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8]; int64_t start_counter = 0; int64_t end_counter = 0; boolean mismatch; for(j = 0; j < 4; ++j) { random_vec(type, src + j*stride); random_vec(type, dst + j*stride); random_vec(type, con + j*stride); } { double fsrc[4]; double fdst[4]; double fcon[4]; double fref[4]; unsigned k; for(k = 0; k < type.length; ++k) { for(j = 0; j < 4; ++j) { fsrc[j] = read_elem(type, src + j*stride, k); fdst[j] = read_elem(type, dst + j*stride, k); fcon[j] = read_elem(type, con + j*stride, k); } compute_blend_ref(blend, fsrc, fdst, fcon, fref); for(j = 0; j < 4; ++j) write_elem(type, ref + j*stride, k, fref[j]); } } start_counter = rdtsc(); blend_test_ptr(src, dst, con, res); end_counter = rdtsc(); cycles[i] = end_counter - start_counter; mismatch = FALSE; for (j = 0; j < 4; ++j) if(!compare_vec(type, res + j*stride, ref + j*stride)) mismatch = TRUE; if (mismatch) { success = FALSE; if(verbose < 1) dump_blend_type(stderr, blend, mode, type); fprintf(stderr, "MISMATCH\n"); for(j = 0; j < 4; ++j) { char channel = "RGBA"[j]; fprintf(stderr, " Src%c: ", channel); dump_vec(stderr, type, src + j*stride); fprintf(stderr, "\n"); fprintf(stderr, " Dst%c: ", channel); dump_vec(stderr, type, dst + j*stride); fprintf(stderr, "\n"); fprintf(stderr, " Con%c: ", channel); dump_vec(stderr, type, con + j*stride); fprintf(stderr, "\n"); fprintf(stderr, " Res%c: ", channel); dump_vec(stderr, type, res + j*stride); fprintf(stderr, "\n"); fprintf(stderr, " Ref%c: ", channel); dump_vec(stderr, type, ref + j*stride); fprintf(stderr, "\n"); } } } } /* * Unfortunately the output of cycle counter is not very reliable as it comes * -- sometimes we get outliers (due IRQs perhaps?) which are * better removed to avoid random or biased data. */ { double sum = 0.0, sum2 = 0.0; double avg, std; unsigned m; for(i = 0; i < n; ++i) { sum += cycles[i]; sum2 += cycles[i]*cycles[i]; } avg = sum/n; std = sqrtf((sum2 - n*avg*avg)/n); m = 0; sum = 0.0; for(i = 0; i < n; ++i) { if(fabs(cycles[i] - avg) <= 4.0*std) { sum += cycles[i]; ++m; } } cycles_avg = sum/m; } if(fp) write_tsv_row(fp, blend, mode, type, cycles_avg, success); if (!success) { if(verbose < 2) LLVMDumpModule(module); LLVMWriteBitcodeToFile(module, "blend.bc"); fprintf(stderr, "blend.bc written\n"); fprintf(stderr, "Invoke as \"llc -o - blend.bc\"\n"); abort(); } LLVMFreeMachineCodeForFunction(engine, func); LLVMDisposeExecutionEngine(engine); if(pass) LLVMDisposePassManager(pass); return success; }
PIPE_ALIGN_STACK static boolean test_round(unsigned verbose, FILE *fp) { LLVMModuleRef module = NULL; LLVMValueRef test_round = NULL, test_trunc, test_floor, test_ceil; LLVMExecutionEngineRef engine = lp_build_engine; LLVMPassManagerRef pass = NULL; char *error = NULL; test_round_t round_func, trunc_func, floor_func, ceil_func; float unpacked[4]; unsigned packed; boolean success = TRUE; int i; module = LLVMModuleCreateWithName("test"); test_round = add_test(module, "round", lp_build_round); test_trunc = add_test(module, "trunc", lp_build_trunc); test_floor = add_test(module, "floor", lp_build_floor); test_ceil = add_test(module, "ceil", lp_build_ceil); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { printf("LLVMVerifyModule: %s\n", error); LLVMDumpModule(module); abort(); } LLVMDisposeMessage(error); #if 0 pass = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, * but there are more on SVN. */ LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); LLVMAddPromoteMemoryToRegisterPass(pass); LLVMAddGVNPass(pass); LLVMAddCFGSimplificationPass(pass); LLVMRunPassManager(pass, module); #else (void)pass; #endif round_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_round)); trunc_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_trunc)); floor_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_floor)); ceil_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_ceil)); memset(unpacked, 0, sizeof unpacked); packed = 0; if (0) LLVMDumpModule(module); for (i = 0; i < 3; i++) { v4sf xvals[3] = { {-10.0, -1, 0, 12.0}, {-1.5, -0.25, 1.25, 2.5}, {-0.99, -0.01, 0.01, 0.99} }; v4sf x = xvals[i]; v4sf y, ref; float *xp = (float *) &x; float *refp = (float *) &ref; printf("\n"); printv("x ", x); refp[0] = round(xp[0]); refp[1] = round(xp[1]); refp[2] = round(xp[2]); refp[3] = round(xp[3]); y = round_func(x); printv("C round(x) ", ref); printv("LLVM round(x)", y); compare(ref, y); refp[0] = trunc(xp[0]); refp[1] = trunc(xp[1]); refp[2] = trunc(xp[2]); refp[3] = trunc(xp[3]); y = trunc_func(x); printv("C trunc(x) ", ref); printv("LLVM trunc(x)", y); compare(ref, y); refp[0] = floor(xp[0]); refp[1] = floor(xp[1]); refp[2] = floor(xp[2]); refp[3] = floor(xp[3]); y = floor_func(x); printv("C floor(x) ", ref); printv("LLVM floor(x)", y); compare(ref, y); refp[0] = ceil(xp[0]); refp[1] = ceil(xp[1]); refp[2] = ceil(xp[2]); refp[3] = ceil(xp[3]); y = ceil_func(x); printv("C ceil(x) ", ref); printv("LLVM ceil(x) ", y); compare(ref, y); } LLVMFreeMachineCodeForFunction(engine, test_round); LLVMFreeMachineCodeForFunction(engine, test_trunc); LLVMFreeMachineCodeForFunction(engine, test_floor); LLVMFreeMachineCodeForFunction(engine, test_ceil); LLVMDisposeExecutionEngine(engine); if(pass) LLVMDisposePassManager(pass); return success; }
/** * Compile an LLVM module to machine code. * * @returns 0 for success, 1 for failure */ unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_llvm_binary *binary, const char * gpu_family, unsigned dump) { LLVMTargetRef target; LLVMTargetMachineRef tm; char cpu[CPU_STRING_LEN]; char fs[FS_STRING_LEN]; char *err; LLVMMemoryBufferRef out_buffer; unsigned buffer_size; const char *buffer_data; char triple[TRIPLE_STRING_LEN]; char *elf_buffer; Elf *elf; Elf_Scn *section = NULL; size_t section_str_index; LLVMBool r; init_r600_target(); target = get_r600_target(); if (!target) { return 1; } strncpy(cpu, gpu_family, CPU_STRING_LEN); memset(fs, 0, sizeof(fs)); if (dump) { LLVMDumpModule(M); strncpy(fs, "+DumpCode", FS_STRING_LEN); } strncpy(triple, "r600--", TRIPLE_STRING_LEN); tm = LLVMCreateTargetMachine(target, triple, cpu, fs, LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault); r = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, &out_buffer); if (r) { fprintf(stderr, "%s", err); FREE(err); return 1; } buffer_size = LLVMGetBufferSize(out_buffer); buffer_data = LLVMGetBufferStart(out_buffer); /* One of the libelf implementations * (http://www.mr511.de/software/english.htm) requires calling * elf_version() before elf_memory(). */ elf_version(EV_CURRENT); elf_buffer = MALLOC(buffer_size); memcpy(elf_buffer, buffer_data, buffer_size); elf = elf_memory(elf_buffer, buffer_size); elf_getshdrstrndx(elf, §ion_str_index); binary->disassembled = 0; while ((section = elf_nextscn(elf, section))) { const char *name; Elf_Data *section_data = NULL; GElf_Shdr section_header; if (gelf_getshdr(section, §ion_header) != §ion_header) { fprintf(stderr, "Failed to read ELF section header\n"); return 1; } name = elf_strptr(elf, section_str_index, section_header.sh_name); if (!strcmp(name, ".text")) { section_data = elf_getdata(section, section_data); binary->code_size = section_data->d_size; binary->code = MALLOC(binary->code_size * sizeof(unsigned char)); memcpy(binary->code, section_data->d_buf, binary->code_size); } else if (!strcmp(name, ".AMDGPU.config")) { section_data = elf_getdata(section, section_data); binary->config_size = section_data->d_size; binary->config = MALLOC(binary->config_size * sizeof(unsigned char)); memcpy(binary->config, section_data->d_buf, binary->config_size); } else if (dump && !strcmp(name, ".AMDGPU.disasm")) { binary->disassembled = 1; section_data = elf_getdata(section, section_data); fprintf(stderr, "\nShader Disassembly:\n\n"); fprintf(stderr, "%.*s\n", (int)section_data->d_size, (char *)section_data->d_buf); } } LLVMDisposeMemoryBuffer(out_buffer); LLVMDisposeTargetMachine(tm); return 0; }
int main(int c, char **v) { LLVMContextRef *contexts; LLVMModuleRef *modules; char *error; const char *mode = "opt"; const char **filenames; unsigned numFiles; unsigned i; bool moreOptions; static int verboseFlag = 0; static int timingFlag = 0; static int disassembleFlag = 0; bool manyContexts = true; double beforeAll; if (c == 1) usage(); moreOptions = true; while (moreOptions) { static struct option longOptions[] = { {"verbose", no_argument, &verboseFlag, 1}, {"timing", no_argument, &timingFlag, 1}, {"disassemble", no_argument, &disassembleFlag, 1}, {"mode", required_argument, 0, 0}, {"contexts", required_argument, 0, 0}, {"help", no_argument, 0, 0} }; int optionIndex; int optionValue; optionValue = getopt_long(c, v, "", longOptions, &optionIndex); switch (optionValue) { case -1: moreOptions = false; break; case 0: { const char* thisOption = longOptions[optionIndex].name; if (!strcmp(thisOption, "help")) usage(); if (!strcmp(thisOption, "contexts")) { if (!strcasecmp(optarg, "one")) manyContexts = false; else if (!strcasecmp(optarg, "many")) manyContexts = true; else { fprintf(stderr, "Invalid argument for --contexts.\n"); exit(1); } break; } if (!strcmp(thisOption, "mode")) { mode = strdup(optarg); break; } break; } case '?': exit(0); break; default: printf("optionValue = %d\n", optionValue); abort(); break; } } LLVMLinkInMCJIT(); LLVMInitializeNativeTarget(); LLVMInitializeX86AsmPrinter(); LLVMInitializeX86Disassembler(); filenames = (const char **)(v + optind); numFiles = c - optind; contexts = malloc(sizeof(LLVMContextRef) * numFiles); modules = malloc(sizeof(LLVMModuleRef) * numFiles); if (manyContexts) { for (i = 0; i < numFiles; ++i) contexts[i] = LLVMContextCreate(); } else { LLVMContextRef context = LLVMContextCreate(); for (i = 0; i < numFiles; ++i) contexts[i] = context; } for (i = 0; i < numFiles; ++i) { LLVMMemoryBufferRef buffer; const char* filename = filenames[i]; if (LLVMCreateMemoryBufferWithContentsOfFile(filename, &buffer, &error)) { fprintf(stderr, "Error reading file %s: %s\n", filename, error); exit(1); } if (LLVMParseBitcodeInContext(contexts[i], buffer, modules + i, &error)) { fprintf(stderr, "Error parsing file %s: %s\n", filename, error); exit(1); } LLVMDisposeMemoryBuffer(buffer); if (verboseFlag) { printf("Module #%u (%s) after parsing:\n", i, filename); LLVMDumpModule(modules[i]); } } if (verboseFlag) printf("Generating code for modules...\n"); if (timingFlag) beforeAll = currentTime(); for (i = 0; i < numFiles; ++i) { LLVMModuleRef module; LLVMExecutionEngineRef engine; struct LLVMMCJITCompilerOptions options; LLVMValueRef value; LLVMPassManagerRef functionPasses = 0; LLVMPassManagerRef modulePasses = 0; double before; if (timingFlag) before = currentTime(); module = modules[i]; LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); options.OptLevel = 2; options.EnableFastISel = 0; options.MCJMM = LLVMCreateSimpleMCJITMemoryManager( 0, mmAllocateCodeSection, mmAllocateDataSection, mmApplyPermissions, mmDestroy); if (LLVMCreateMCJITCompilerForModule(&engine, module, &options, sizeof(options), &error)) { fprintf(stderr, "Error building MCJIT: %s\n", error); exit(1); } if (!strcasecmp(mode, "simple")) { modulePasses = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses); LLVMAddConstantPropagationPass(modulePasses); LLVMAddInstructionCombiningPass(modulePasses); LLVMAddPromoteMemoryToRegisterPass(modulePasses); LLVMAddBasicAliasAnalysisPass(modulePasses); LLVMAddTypeBasedAliasAnalysisPass(modulePasses); LLVMAddGVNPass(modulePasses); LLVMAddCFGSimplificationPass(modulePasses); LLVMRunPassManager(modulePasses, module); } else if (!strcasecmp(mode, "opt")) { LLVMPassManagerBuilderRef passBuilder; passBuilder = LLVMPassManagerBuilderCreate(); LLVMPassManagerBuilderSetOptLevel(passBuilder, 2); LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0); functionPasses = LLVMCreateFunctionPassManagerForModule(module); modulePasses = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses); LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, functionPasses); LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses); LLVMPassManagerBuilderDispose(passBuilder); LLVMInitializeFunctionPassManager(functionPasses); for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) LLVMRunFunctionPassManager(functionPasses, value); LLVMFinalizeFunctionPassManager(functionPasses); LLVMRunPassManager(modulePasses, module); } else { fprintf(stderr, "Bad optimization mode: %s.\n", mode); fprintf(stderr, "Valid modes are: \"simple\" or \"opt\".\n"); exit(1); } if (verboseFlag) { printf("Module #%d (%s) after optimization:\n", i, filenames[i]); LLVMDumpModule(module); } for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) { if (LLVMIsDeclaration(value)) continue; LLVMGetPointerToGlobal(engine, value); } if (functionPasses) LLVMDisposePassManager(functionPasses); if (modulePasses) LLVMDisposePassManager(modulePasses); LLVMDisposeExecutionEngine(engine); if (timingFlag) { double after = currentTime(); printf("Module #%d (%s) took %lf ms.\n", i, filenames[i], (after - before) * 1000); } } if (timingFlag) { double after = currentTime(); printf("Compilation took a total of %lf ms.\n", (after - beforeAll) * 1000); } if (disassembleFlag) { LLVMDisasmContextRef disassembler; struct MemorySection *section; disassembler = LLVMCreateDisasm("x86_64-apple-darwin", 0, 0, 0, symbolLookupCallback); if (!disassembler) { fprintf(stderr, "Error building disassembler.\n"); exit(1); } for (section = sectionHead; section; section = section->next) { printf("Disassembly for section %p:\n", section); char pcString[20]; char instructionString[1000]; uint8_t *pc; uint8_t *end; pc = section->start; end = pc + section->size; while (pc < end) { snprintf( pcString, sizeof(pcString), "0x%lx", (unsigned long)(uintptr_t)pc); size_t instructionSize = LLVMDisasmInstruction( disassembler, pc, end - pc, (uintptr_t)pc, instructionString, sizeof(instructionString)); if (!instructionSize) snprintf(instructionString, sizeof(instructionString), ".byte 0x%02x", *pc++); else pc += instructionSize; printf(" %16s: %s\n", pcString, instructionString); } } } return 0; }
int main(int argc, char** argv) { llvm::llvm_shutdown_obj Y; llvm::error_code ec; std::string se; std::string file; if (argc < 2) { llvm::errs() << "Usage llvm-disasm <file>\n"; return 1; } llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); file = argv[1]; llvm::OwningPtr<llvm::object::Binary> bin; ec = llvm::object::createBinary(file, bin); if (ec) { llvm::errs() << file << ": " << ec.message() << "\n"; return 1; } if (!bin->isELF()) { llvm::errs() << file << " isn't an object file\n"; return 1; } llvm::object::ObjectFile* obj = llvm::dyn_cast<llvm::object::ObjectFile>(bin.get()); if (!obj) { llvm::errs() << file << ": failed to cast to llvm::ObjectFile\n"; return 1; } llvm::Triple tri; tri.setArch(llvm::Triple::ArchType(obj->getArch())); std::string targetName = tri.str(); const llvm::Target* target = llvm::TargetRegistry::lookupTarget(targetName, se); if (!target) { llvm::errs() << file << ": failed to get the target descriptor for " << targetName << "\n"; return 1; } STI = target->createMCSubtargetInfo(targetName, "", ""); if (!STI) { llvm::errs() << file << ": " << ": to get the subtarget info!\n"; return 1; } disasm = target->createMCDisassembler(*STI); if (!disasm) { llvm::errs() << file << ": " << ": to get the disassembler!\n"; return 1; } MII = target->createMCInstrInfo(); if (!MII) { llvm::errs() << file << ": no instruction info for target\n"; return 1; } MRI = target->createMCRegInfo(targetName); if (!MRI) { llvm::errs() << file << ": no register info for target\n"; return 1; } llvmBuilder = LLVMCreateBuilder(); LLVMModuleRef llvmModule = LLVMModuleCreateWithName("test"); LLVMTypeRef mainType = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0); LLVMValueRef mainFn = LLVMAddFunction(llvmModule, "main", mainType); LLVMBasicBlockRef blk = LLVMAppendBasicBlock(mainFn, ""); LLVMPositionBuilderAtEnd(llvmBuilder, blk); for (llvm::object::section_iterator i = obj->begin_sections(), e = obj->end_sections(); i != e; i.increment(ec)) { if (ec) { llvm::errs() << "Failed to increment the section iterator!\n"; return 1; } bool isText; llvm::StringRef secName; if (i->getName(secName)) { llvm::errs() << file << ": failed to get the section name\n"; break; } if (i->isText(isText)) { llvm::errs() << file << ": " << secName << ": failed to determine the section type\n"; break; } if (!isText) { continue; } std::set<llvm::object::SymbolRef> symbols; for (llvm::object::symbol_iterator isym = obj->begin_symbols(); isym != obj->end_symbols(); isym.increment(ec)) { bool res; llvm::StringRef symName; llvm::object::SymbolRef::Type symType; if (ec) { llvm::errs() << "Failed to increment the symbol iterator!\n"; return 1; } if (isym->getName(symName)) { llvm::errs() << file << ": " << secName << ": failed to get the symbol name!\n"; return 1; } /* uint64_t secSize, secBase, symAddr; i->getAddress(secBase); i->getSize(secSize); isym->getAddress(symAddr); if (i->containsSymbol(*isym, res)) { llvm::errs() << file << ": " << secName << ": " << symName << ": failed to check whether the symbol is in the section!\n"; return 1; } if (!res) { continue; } if (symAddr < secBase || symAddr >= secBase + secSize) { continue; } */ llvm::object::section_iterator i2 = llvm::object::section_iterator(llvm::object::SectionRef()); isym->getSection(i2); if (i2 != i) { continue; } if (isym->getType(symType)) { llvm::errs() << file << ": " << secName << ": " << symName << ": failed to get the symbol type!\n"; return 1; } if (symType != llvm::object::SymbolRef::ST_Function) { continue; } symbols.insert(*isym); } for (std::set<llvm::object::SymbolRef>::const_iterator isym = symbols.begin(); isym != symbols.end(); ++isym) { if (analyzeSymbol(*isym)) { return 1; } } } LLVMDumpModule(llvmModule); LLVMDisposeModule(llvmModule); LLVMDisposeBuilder(llvmBuilder); return 0; }
PIPE_ALIGN_STACK static boolean test_one(unsigned verbose, FILE *fp, struct lp_type src_type, struct lp_type dst_type) { LLVMModuleRef module = NULL; LLVMValueRef func = NULL; LLVMExecutionEngineRef engine = NULL; LLVMModuleProviderRef provider = NULL; LLVMPassManagerRef pass = NULL; char *error = NULL; conv_test_ptr_t conv_test_ptr; boolean success; const unsigned n = LP_TEST_NUM_SAMPLES; int64_t cycles[LP_TEST_NUM_SAMPLES]; double cycles_avg = 0.0; unsigned num_srcs; unsigned num_dsts; double eps; unsigned i, j; if(verbose >= 1) dump_conv_types(stdout, src_type, dst_type); if(src_type.length > dst_type.length) { num_srcs = 1; num_dsts = src_type.length/dst_type.length; } else { num_dsts = 1; num_srcs = dst_type.length/src_type.length; } assert(src_type.width * src_type.length == dst_type.width * dst_type.length); /* We must not loose or gain channels. Only precision */ assert(src_type.length * num_srcs == dst_type.length * num_dsts); eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type)); module = LLVMModuleCreateWithName("test"); func = add_conv_test(module, src_type, num_srcs, dst_type, num_dsts); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { LLVMDumpModule(module); abort(); } LLVMDisposeMessage(error); provider = LLVMCreateModuleProviderForExistingModule(module); if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) { if(verbose < 1) dump_conv_types(stderr, src_type, dst_type); fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); abort(); } #if 0 pass = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, * but there are more on SVN. */ LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); LLVMAddPromoteMemoryToRegisterPass(pass); LLVMAddGVNPass(pass); LLVMAddCFGSimplificationPass(pass); LLVMRunPassManager(pass, module); #else (void)pass; #endif if(verbose >= 2) LLVMDumpModule(module); conv_test_ptr = (conv_test_ptr_t)LLVMGetPointerToGlobal(engine, func); if(verbose >= 2) lp_disassemble(conv_test_ptr); success = TRUE; for(i = 0; i < n && success; ++i) { unsigned src_stride = src_type.length*src_type.width/8; unsigned dst_stride = dst_type.length*dst_type.width/8; PIPE_ALIGN_VAR(16) uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; PIPE_ALIGN_VAR(16) uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; double fref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; uint8_t ref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; int64_t start_counter = 0; int64_t end_counter = 0; for(j = 0; j < num_srcs; ++j) { random_vec(src_type, src + j*src_stride); read_vec(src_type, src + j*src_stride, fref + j*src_type.length); } for(j = 0; j < num_dsts; ++j) { write_vec(dst_type, ref + j*dst_stride, fref + j*dst_type.length); } start_counter = rdtsc(); conv_test_ptr(src, dst); end_counter = rdtsc(); cycles[i] = end_counter - start_counter; for(j = 0; j < num_dsts; ++j) { if(!compare_vec_with_eps(dst_type, dst + j*dst_stride, ref + j*dst_stride, eps)) success = FALSE; } if (!success) { if(verbose < 1) dump_conv_types(stderr, src_type, dst_type); fprintf(stderr, "MISMATCH\n"); for(j = 0; j < num_srcs; ++j) { fprintf(stderr, " Src%u: ", j); dump_vec(stderr, src_type, src + j*src_stride); fprintf(stderr, "\n"); } #if 1 fprintf(stderr, " Ref: "); for(j = 0; j < src_type.length*num_srcs; ++j) fprintf(stderr, " %f", fref[j]); fprintf(stderr, "\n"); #endif for(j = 0; j < num_dsts; ++j) { fprintf(stderr, " Dst%u: ", j); dump_vec(stderr, dst_type, dst + j*dst_stride); fprintf(stderr, "\n"); fprintf(stderr, " Ref%u: ", j); dump_vec(stderr, dst_type, ref + j*dst_stride); fprintf(stderr, "\n"); } } } /* * Unfortunately the output of cycle counter is not very reliable as it comes * -- sometimes we get outliers (due IRQs perhaps?) which are * better removed to avoid random or biased data. */ { double sum = 0.0, sum2 = 0.0; double avg, std; unsigned m; for(i = 0; i < n; ++i) { sum += cycles[i]; sum2 += cycles[i]*cycles[i]; } avg = sum/n; std = sqrtf((sum2 - n*avg*avg)/n); m = 0; sum = 0.0; for(i = 0; i < n; ++i) { if(fabs(cycles[i] - avg) <= 4.0*std) { sum += cycles[i]; ++m; } } cycles_avg = sum/m; } if(fp) write_tsv_row(fp, src_type, dst_type, cycles_avg, success); if (!success) { static boolean firsttime = TRUE; if(firsttime) { if(verbose < 2) LLVMDumpModule(module); LLVMWriteBitcodeToFile(module, "conv.bc"); fprintf(stderr, "conv.bc written\n"); fprintf(stderr, "Invoke as \"llc -o - conv.bc\"\n"); firsttime = FALSE; /* abort(); */ } } LLVMFreeMachineCodeForFunction(engine, func); LLVMDisposeExecutionEngine(engine); if(pass) LLVMDisposePassManager(pass); return success; }