static void radeon_llvm_optimize(LLVMModuleRef mod) { const char *data_layout = LLVMGetDataLayout(mod); LLVMTargetDataRef TD = LLVMCreateTargetData(data_layout); LLVMPassManagerBuilderRef builder = LLVMPassManagerBuilderCreate(); LLVMPassManagerRef pass_manager = LLVMCreatePassManager(); /* Functions calls are not supported yet, so we need to inline * everything. The most efficient way to do this is to add * the always_inline attribute to all non-kernel functions * and then run the Always Inline pass. The Always Inline * pass will automaically inline functions with this attribute * and does not perform the expensive cost analysis that the normal * inliner does. */ LLVMValueRef fn; for (fn = LLVMGetFirstFunction(mod); fn; fn = LLVMGetNextFunction(fn)) { /* All the non-kernel functions have internal linkage */ if (LLVMGetLinkage(fn) == LLVMInternalLinkage) { LLVMAddFunctionAttr(fn, LLVMAlwaysInlineAttribute); } } LLVMAddTargetData(TD, pass_manager); LLVMAddAlwaysInlinerPass(pass_manager); LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager); LLVMRunPassManager(pass_manager, mod); LLVMPassManagerBuilderDispose(builder); LLVMDisposePassManager(pass_manager); LLVMDisposeTargetData(TD); }
/* ExecutionEngine.t -> Llvm_target.DataLayout.t */ CAMLprim value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) { value DataLayout; LLVMTargetDataRef OrigDataLayout; char* TargetDataCStr; OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); LLVMDisposeMessage(TargetDataCStr); return DataLayout; }
static LLVMValueRef translateArrayExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { PtrVector *V = &(Node->Child); ASTNode *SizeNode = (ASTNode*) ptrVectorGet(V, 0), *InitNode = (ASTNode*) ptrVectorGet(V, 1); Type *ThisType = createType(IdTy, Node->Value); LLVMTypeRef ArrayType = getLLVMTypeFromType(TyTable, ThisType); LLVMValueRef SizeVal = translateExpr(TyTable, ValTable, SizeNode), InitVal = translateExpr(TyTable, ValTable, InitNode); LLVMValueRef ArrayVal = LLVMBuildArrayMalloc(Builder, ArrayType, SizeVal, ""); // This BasicBlock and ThisFunction LLVMBasicBlockRef ThisBB = LLVMGetInsertBlock(Builder); LLVMValueRef ThisFn = LLVMGetBasicBlockParent(ThisBB); LLVMValueRef Counter = LLVMBuildAlloca(Builder, LLVMInt32Type(), ""); LLVMBuildStore(Builder, LLVMConstInt(LLVMInt32Type(), 0, 1), Counter); LLVMTargetDataRef DataRef = LLVMCreateTargetData(LLVMGetDataLayout(Module)); unsigned long long Size = LLVMStoreSizeOfType(DataRef, ArrayType); LLVMBasicBlockRef InitBB, MidBB, EndBB; InitBB = LLVMAppendBasicBlock(ThisFn, "for.init"); EndBB = LLVMAppendBasicBlock(ThisFn, "for.end"); MidBB = LLVMAppendBasicBlock(ThisFn, "for.mid"); LLVMBuildBr(Builder, InitBB); LLVMPositionBuilderAtEnd(Builder, InitBB); LLVMValueRef CurrentCounter = LLVMBuildLoad(Builder, Counter, ""); LLVMValueRef Comparation = LLVMBuildICmp(Builder, LLVMIntSLT, CurrentCounter, SizeVal, ""); LLVMBuildCondBr(Builder, Comparation, MidBB, EndBB); LLVMPositionBuilderAtEnd(Builder, MidBB); CurrentCounter = LLVMBuildLoad(Builder, Counter, ""); LLVMValueRef TheValue = LLVMBuildLoad(Builder, InitVal, ""); LLVMValueRef ElemIdx[] = { LLVMConstInt(LLVMInt32Type(), 0, 1), CurrentCounter }; LLVMValueRef Elem = LLVMBuildInBoundsGEP(Builder, ArrayVal, ElemIdx, 2, ""); copyMemory(Elem, TheValue, getSConstInt(Size)); LLVMBuildBr(Builder, InitBB); LLVMPositionBuilderAtEnd(Builder, EndBB); return ArrayVal; }
/* TargetMachine.t -> DataLayout.t */ CAMLprim value llvm_targetmachine_data_layout(value Machine) { CAMLparam1(Machine); CAMLlocal1(DataLayout); /* LLVMGetTargetMachineData returns a pointer owned by the TargetMachine, so it is impossible to wrap it with llvm_alloc_target_data, which assumes that OCaml owns the pointer. */ LLVMTargetDataRef OrigDataLayout; OrigDataLayout = LLVMGetTargetMachineData(TargetMachine_val(Machine)); char* TargetDataCStr; TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); LLVMDisposeMessage(TargetDataCStr); CAMLreturn(DataLayout); }
/* string -> TargetData.t */ CAMLprim LLVMTargetDataRef llvm_targetdata_create(value StringRep) { return LLVMCreateTargetData(String_val(StringRep)); }
/* string -> DataLayout.t */ CAMLprim value llvm_datalayout_of_string(value StringRep) { return llvm_alloc_data_layout(LLVMCreateTargetData(String_val(StringRep))); }
/** * Allocate gallivm LLVM objects. * \return TRUE for success, FALSE for failure */ static boolean init_gallivm_state(struct gallivm_state *gallivm) { assert(!gallivm->context); assert(!gallivm->module); assert(!gallivm->provider); lp_build_init(); if (!gallivm_context) { gallivm_context = LLVMContextCreate(); } gallivm->context = gallivm_context; if (!gallivm->context) goto fail; gallivm->module = LLVMModuleCreateWithNameInContext("gallivm", gallivm->context); if (!gallivm->module) goto fail; gallivm->provider = LLVMCreateModuleProviderForExistingModule(gallivm->module); if (!gallivm->provider) goto fail; gallivm->builder = LLVMCreateBuilderInContext(gallivm->context); if (!gallivm->builder) goto fail; /* FIXME: MC-JIT only allows compiling one module at a time, and it must be * complete when MC-JIT is created. So defer the MC-JIT engine creation for * now. */ #if !USE_MCJIT if (!init_gallivm_engine(gallivm)) { goto fail; } #else /* * MC-JIT engine compiles the module immediately on creation, so we can't * obtain the target data from it. Instead we create a target data layout * from a string. * * The produced layout strings are not precisely the same, but should make * no difference for the kind of optimization passes we run. * * For reference this is the layout string on x64: * * e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64 * * See also: * - http://llvm.org/docs/LangRef.html#datalayout */ { const unsigned pointer_size = 8 * sizeof(void *); char layout[512]; util_snprintf(layout, sizeof layout, "%c-p:%u:%u:%u-i64:64:64-a0:0:%u-s0:%u:%u", #ifdef PIPE_ARCH_LITTLE_ENDIAN 'e', // little endian #else 'E', // big endian #endif pointer_size, pointer_size, pointer_size, // pointer size, abi alignment, preferred alignment pointer_size, // aggregate preferred alignment pointer_size, pointer_size); // stack objects abi alignment, preferred alignment gallivm->target = LLVMCreateTargetData(layout); if (!gallivm->target) { return FALSE; } } #endif if (!create_pass_manager(gallivm)) goto fail; return TRUE; fail: free_gallivm_state(gallivm); return FALSE; }